=======
var lastPositionedGlyph = positionedGlyphs[positionedGlyphs.length - 1];
var lastLineLength = lastPositionedGlyph.x + glyphs[lastPositionedGlyph.codePoint].advance;
maxLineLength = Math.max(maxLineLength, lastLineLength);
var height = (line + 1) * lineHeight;
justifyLine(positionedGlyphs, glyphs, lineStartIndex, positionedGlyphs.length - 1, justify);
align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line);
// Calculate the bounding box
shaping.top += -verticalAlign * height;
shaping.bottom = shaping.top + height;
shaping.left += -horizontalAlign * maxLineLength;
shaping.right = shaping.left + maxLineLength;
}
function justifyLine(positionedGlyphs, glyphs, start, end, justify) {
var lastAdvance = glyphs[positionedGlyphs[end].codePoint].advance;
var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
for (var j = start; j <= end; j++) {
positionedGlyphs[j].x -= lineIndent;
}
}
function align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line) {
var shiftX = (justify - horizontalAlign) * maxLineLength;
var shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight;
for (var j = 0; j < positionedGlyphs.length; j++) {
positionedGlyphs[j].x += shiftX;
positionedGlyphs[j].y += shiftY;
}
}
function shapeIcon(image, layout) {
if (!image || !image.rect) return null;
var dx = layout['icon-offset'][0];
var dy = layout['icon-offset'][1];
var x1 = dx - image.width / 2;
var x2 = x1 + image.width;
var y1 = dy - image.height / 2;
var y2 = y1 + image.height;
return new PositionedIcon(image, y1, y2, x1, x2);
}
function PositionedIcon(image, top, bottom, left, right) {
this.image = image;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
}
},{}],73:[function(require,module,exports){
'use strict';
var BinPack = require('./bin_pack');
module.exports = SpriteAtlas;
function SpriteAtlas(width, height) {
this.width = width;
this.height = height;
this.bin = new BinPack(width, height);
this.images = {};
this.data = false;
this.texture = 0; // WebGL ID
this.filter = 0; // WebGL ID
this.pixelRatio = 1;
this.dirty = true;
}
SpriteAtlas.prototype = {
get debug() {
return 'canvas' in this;
},
set debug(value) {
if (value && !this.canvas) {
this.canvas = document.createElement('canvas');
this.canvas.width = this.width * this.pixelRatio;
this.canvas.height = this.height * this.pixelRatio;
this.canvas.style.width = this.width + 'px';
this.canvas.style.width = this.width + 'px';
document.body.appendChild(this.canvas);
this.ctx = this.canvas.getContext('2d');
} else if (!value && this.canvas) {
this.canvas.parentNode.removeChild(this.canvas);
delete this.ctx;
delete this.canvas;
}
}
};
SpriteAtlas.prototype.resize = function(newRatio) {
if (this.pixelRatio === newRatio) return false;
var oldRatio = this.pixelRatio;
this.pixelRatio = newRatio;
if (this.canvas) {
this.canvas.width = this.width * this.pixelRatio;
this.canvas.height = this.height * this.pixelRatio;
}
if (this.data) {
var oldData = this.data;
this.data = false;
this.allocate();
this.texture = false;
var oldWidth = this.width * oldRatio;
var oldHeight = this.height * oldRatio;
var newWidth = this.width * newRatio;
var newHeight = this.height * newRatio;
// Basic image scaling. TODO: Replace this with better image scaling.
var newImage = this.data;
var oldImage = oldData;
for (var y = 0; y < newHeight; y++) {
var oldYOffset = Math.floor((y * oldHeight) / newHeight) * oldWidth;
var newYOffset = y * newWidth;
for (var x = 0; x < newWidth; x++) {
var oldX = Math.floor((x * oldWidth) / newWidth);
newImage[newYOffset + x] = oldImage[oldYOffset + oldX];
}
}
oldData = null;
this.dirty = true;
}
return this.dirty;
};
function copyBitmap(src, srcStride, srcX, srcY, dst, dstStride, dstX, dstY, width, height, wrap) {
var srcI = srcY * srcStride + srcX;
var dstI = dstY * dstStride + dstX;
var x, y;
if (wrap) {
// add 1 pixel wrapped padding on each side of the image
dstI -= dstStride;
for (y = -1; y <= height; y++, srcI = ((y + height) % height + srcY) * srcStride + srcX, dstI += dstStride) {
for (x = -1; x <= width; x++) {
dst[dstI + x] = src[srcI + ((x + width) % width)];
}
}
} else {
for (y = 0; y < height; y++, srcI += srcStride, dstI += dstStride) {
for (x = 0; x < width; x++) {
dst[dstI + x] = src[srcI + x];
}
}
}
}
SpriteAtlas.prototype.allocateImage = function(pixelWidth, pixelHeight) {
// Increase to next number divisible by 4, but at least 1.
// This is so we can scale down the texture coordinates and pack them
// into 2 bytes rather than 4 bytes.
// Pad icons to prevent them from polluting neighbours during linear interpolation
var padding = 2;
var packWidth = pixelWidth + padding + (4 - (pixelWidth + padding) % 4);
var packHeight = pixelHeight + padding + (4 - (pixelHeight + padding) % 4);// + 4;
// We have to allocate a new area in the bin, and store an empty image in it.
// Add a 1px border around every image.
var rect = this.bin.allocate(packWidth, packHeight);
if (rect.w === 0) {
return rect;
}
rect.originalWidth = pixelWidth;
rect.originalHeight = pixelHeight;
return rect;
};
SpriteAtlas.prototype.getImage = function(name, wrap) {
if (this.images[name]) {
return this.images[name];
}
if (!this.sprite) {
return null;
}
var pos = this.sprite.getSpritePosition(name);
if (!pos.width || !pos.height) {
return null;
}
var width = pos.width / pos.pixelRatio;
var height = pos.height / pos.pixelRatio;
var rect = this.allocateImage(width, height);
if (rect.w === 0) {
return rect;
}
var image = new AtlasImage(rect, width, height, pos.sdf);
this.images[name] = image;
this.copy(rect, pos, wrap);
return image;
};
SpriteAtlas.prototype.getPosition = function(name, repeating) {
var image = this.getImage(name, repeating);
var rect = image && image.rect;
if (!rect) {
return null;
}
// When the image is repeating, get the correct position of the image, rather than the
// one rounded up to 4 pixels.
var width = repeating ? image.width : rect.w;
var height = repeating ? image.height : rect.h;
var padding = 1;
return {
size: [width, height],
tl: [(rect.x + padding) / this.width, (rect.y + padding) / this.height],
br: [(rect.x + padding + width) / this.width, (rect.y + padding + height) / this.height]
};
};
SpriteAtlas.prototype.allocate = function() {
if (!this.data) {
var w = Math.floor(this.width * this.pixelRatio);
var h = Math.floor(this.height * this.pixelRatio);
this.data = new Uint32Array(w * h);
for (var i = 0; i < this.data.length; i++) {
this.data[i] = 0;
}
}
};
SpriteAtlas.prototype.copy = function(dst, src, wrap) {
// if (!sprite->raster) return;
if (!this.sprite.img.data) return;
var srcImg = new Uint32Array(this.sprite.img.data.buffer);
this.allocate();
var dstImg = this.data;
var padding = 1;
copyBitmap(
/* source buffer */ srcImg,
/* source stride */ this.sprite.img.width,
/* source x */ src.x,
/* source y */ src.y,
/* dest buffer */ dstImg,
/* dest stride */ this.width * this.pixelRatio,
/* dest x */ (dst.x + padding) * this.pixelRatio,
/* dest y */ (dst.y + padding) * this.pixelRatio,
/* icon dimension */ src.width,
/* icon dimension */ src.height,
/* wrap */ wrap
);
this.dirty = true;
};
SpriteAtlas.prototype.setSprite = function(sprite) {
this.sprite = sprite;
};
SpriteAtlas.prototype.addIcons = function(icons, callback) {
for (var i = 0; i < icons.length; i++) {
this.getImage(icons[i]);
}
callback(null, this.images);
};
SpriteAtlas.prototype.bind = function(gl, linear) {
var first = false;
if (!this.texture) {
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
first = true;
} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);
}
var filterVal = linear ? gl.LINEAR : gl.NEAREST;
if (filterVal !== this.filter) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterVal);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterVal);
this.filter = filterVal;
}
if (this.dirty) {
this.allocate();
if (first) {
gl.texImage2D(
gl.TEXTURE_2D, // enum target
0, // ind level
gl.RGBA, // ind internalformat
this.width * this.pixelRatio, // GLsizei width
this.height * this.pixelRatio, // GLsizei height
0, // ind border
gl.RGBA, // enum format
gl.UNSIGNED_BYTE, // enum type
new Uint8Array(this.data.buffer) // Object data
);
} else {
gl.texSubImage2D(
gl.TEXTURE_2D, // enum target
0, // int level
0, // int xoffset
0, // int yoffset
this.width * this.pixelRatio, // long width
this.height * this.pixelRatio, // long height
gl.RGBA, // enum format
gl.UNSIGNED_BYTE, // enum type
new Uint8Array(this.data.buffer) // Object pixels
);
}
this.dirty = false;
// DEBUG
if (this.ctx) {
var data = this.ctx.getImageData(0, 0, this.width * this.pixelRatio, this.height * this.pixelRatio);
data.data.set(new Uint8ClampedArray(this.data.buffer));
this.ctx.putImageData(data, 0, 0);
this.ctx.strokeStyle = 'red';
for (var k = 0; k < this.bin.free.length; k++) {
var free = this.bin.free[k];
this.ctx.strokeRect(free.x * this.pixelRatio, free.y * this.pixelRatio, free.w * this.pixelRatio, free.h * this.pixelRatio);
}
}
// END DEBUG
}
};
function AtlasImage(rect, width, height, sdf) {
this.rect = rect;
this.width = width;
this.height = height;
this.sdf = sdf;
}
},{"./bin_pack":59}],74:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var interpolate = require('../util/interpolate');
var browser = require('../util/browser');
var LatLng = require('../geo/lat_lng');
var LatLngBounds = require('../geo/lat_lng_bounds');
var Point = require('point-geometry');
/**
* @typedef {Object} CameraOptions
* @property {Array} [center] Latitude and longitude (passed as `[lat, lng]`)
* @property {number} [zoom] Map zoom level
* @property {number} [bearing] Map rotation bearing in degrees counter-clockwise from north
* @property {number} [pitch] The angle at which the camera is looking at the ground
*/
/**
* @typedef {Object} [AnimationOptions]
* @property {number} [duration=500] Number in milliseconds
* @property {Function} [easing]
* @property {Array} [offset=[0,0]] point, origin of movement relative to map center
* @property {boolean} [animate=true] When set to false, no animation happens
*/
var Camera = module.exports = function() {};
util.extend(Camera.prototype, /** @lends Map.prototype */{
/**
* Get the current view geographical point.
* @returns {LatLng}
*/
getCenter: function() { return this.transform.center; },
/**
* Sets a map location. Equivalent to `jumpTo({center: center})`.
*
* @param {Array} center Latitude and longitude (passed as `[lat, lng]`)
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* map.setCenter([-74, 38]);
*/
setCenter: function(center) {
this.jumpTo({center: center});
},
/**
* Pan by a certain number of pixels
*
* @param {Array} offset [x, y]
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
panBy: function(offset, options) {
this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));
return this;
},
/**
* Pan to a certain location with easing
*
* @param {Object} latlng a `LatLng` object
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
panTo: function(latlng, options) {
this.stop();
latlng = LatLng.convert(latlng);
options = util.extend({
duration: 500,
easing: util.ease,
offset: [0, 0]
}, options);
var tr = this.transform,
offset = Point.convert(options.offset).rotate(-tr.angle),
from = tr.point,
to = tr.project(latlng).sub(offset);
if (!options.noMoveStart) {
this.fire('movestart');
}
this._ease(function(k) {
tr.center = tr.unproject(from.add(to.sub(from).mult(k)));
this.fire('move');
}, function() {
this.fire('moveend');
}, options);
return this;
},
/**
* Get the current zoom
* @returns {number}
*/
getZoom: function() { return this.transform.zoom; },
/**
* Sets a map zoom. Equivalent to `jumpTo({zoom: zoom})`.
*
* @param {number} zoom Map zoom level
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* // zoom the map to 5
* map.setZoom(5);
*/
setZoom: function(zoom) {
this.jumpTo({zoom: zoom});
},
/**
* Zooms to a certain zoom level with easing.
*
* @param {Number} zoom
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomTo: function(zoom, options) {
this.stop();
options = util.extend({
duration: 500
}, options);
options.easing = this._updateEasing(options.duration, zoom, options.easing);
var tr = this.transform,
around = tr.center,
startZoom = tr.zoom;
if (options.around) {
around = LatLng.convert(options.around);
} else if (options.offset) {
around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));
}
if (options.animate === false) options.duration = 0;
if (!this.zooming) {
this.zooming = true;
this.fire('movestart');
}
this._ease(function(k) {
tr.setZoomAround(interpolate(startZoom, zoom, k), around);
this.fire('move').fire('zoom');
}, function() {
this.ease = null;
if (options.duration >= 200) {
this.zooming = false;
this.fire('moveend');
}
}, options);
if (options.duration < 200) {
clearTimeout(this._onZoomEnd);
this._onZoomEnd = setTimeout(function() {
this.zooming = false;
this.fire('moveend');
}.bind(this), 200);
}
return this;
},
/**
* Zoom in by 1 level
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomIn: function(options) {
this.zoomTo(this.getZoom() + 1, options);
},
/**
* Zoom out by 1 level
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomOut: function(options) {
this.zoomTo(this.getZoom() - 1, options);
},
/**
* Get the current bearing in degrees
* @returns {number}
*/
getBearing: function() { return this.transform.bearing; },
/**
* Sets a map rotation. Equivalent to `jumpTo({bearing: bearing})`.
*
* @param {number} bearing Map rotation bearing in degrees counter-clockwise from north
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* // rotate the map to 90 degrees
* map.setBearing(90);
*/
setBearing: function(bearing) {
this.jumpTo({bearing: bearing});
},
/**
* Rotate bearing by a certain number of degrees with easing
*
* @param {Number} bearing
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
rotateTo: function(bearing, options) {
this.stop();
options = util.extend({
duration: 500,
easing: util.ease
}, options);
var tr = this.transform,
start = this.getBearing(),
around = tr.center;
if (options.around) {
around = LatLng.convert(options.around);
} else if (options.offset) {
around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));
}
bearing = this._normalizeBearing(bearing, start);
this.rotating = true;
this.fire('movestart');
this._ease(function(k) {
tr.setBearingAround(interpolate(start, bearing, k), around);
this.fire('move').fire('rotate');
}, function() {
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
/**
* Sets map bearing to 0 (north) with easing
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
resetNorth: function(options) {
return this.rotateTo(0, util.extend({duration: 1000}, options));
},
/**
* Get the current angle in degrees
* @returns {number}
*/
getPitch: function() { return this.transform.pitch; },
/**
* Sets a map angle. Equivalent to `jumpTo({pitch: pitch})`.
*
* @param {number} pitch The angle at which the camera is looking at the ground
* @fires movestart
* @fires moveend
* @returns {Map} `this`
*/
setPitch: function(pitch) {
this.jumpTo({pitch: pitch});
},
/**
* Zoom to contain certain geographical bounds
*
* @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]
* @param {Object} options
* @param {Number} [options.speed=1.2] How fast animation occurs
* @param {Number} [options.curve=1.42] How much zooming out occurs during animation
* @param {Function} options.easing
* @param {Number} options.padding how much padding there is around the given bounds on each side in pixels
* @param {Number} options.maxZoom
* @fires movestart
* @fires moveend
* @returns {this}
*/
fitBounds: function(bounds, options) {
options = util.extend({
padding: 0,
offset: [0, 0],
maxZoom: Infinity
}, options);
bounds = LatLngBounds.convert(bounds);
var offset = Point.convert(options.offset),
tr = this.transform,
nw = tr.project(bounds.getNorthWest()),
se = tr.project(bounds.getSouthEast()),
size = se.sub(nw),
scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,
scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y;
options.center = tr.unproject(nw.add(se).div(2));
options.zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);
options.bearing = 0;
return options.linear ?
this.easeTo(options) :
this.flyTo(options);
},
/**
* Change any combination of center, zoom, bearing, and pitch, without
* a transition. The map will retain the current values for any options
* not included in `options`.
*
* @param {CameraOptions} options map view options
* @fires movestart
* @fires moveend
* @returns {Map} `this`
*/
jumpTo: function(options) {
this.stop();
var tr = this.transform,
zoomChanged = false,
bearingChanged = false,
pitchChanged = false;
if ('center' in options) {
tr.center = LatLng.convert(options.center);
}
if ('zoom' in options && tr.zoom !== +options.zoom) {
zoomChanged = true;
tr.zoom = +options.zoom;
}
if ('bearing' in options && tr.bearing !== +options.bearing) {
bearingChanged = true;
tr.bearing = +options.bearing;
}
if ('pitch' in options && tr.pitch !== +options.pitch) {
pitchChanged = true;
tr.pitch = +options.pitch;
}
this.fire('movestart')
.fire('move');
if (zoomChanged) {
this.fire('zoom');
}
if (bearingChanged) {
this.fire('rotate');
}
if (pitchChanged) {
this.fire('pitch');
}
return this.fire('moveend');
},
/**
* Easing animation to a specified location/zoom/bearing
*
* @param {CameraOptions+AnimationOptions} options map view and animation options
* @fires movestart
* @fires moveend
* @returns {this}
*/
easeTo: function(options) {
this.stop();
options = util.extend({
offset: [0, 0],
duration: 500,
easing: util.ease
}, options);
var tr = this.transform,
offset = Point.convert(options.offset).rotate(-tr.angle),
from = tr.point,
startZoom = this.getZoom(),
startBearing = this.getBearing(),
startPitch = this.getPitch();
var zoom = 'zoom' in options ? +options.zoom : startZoom;
var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing;
var pitch = 'pitch' in options ? +options.pitch : startPitch;
var scale = tr.zoomScale(zoom - startZoom),
to = 'center' in options ? tr.project(LatLng.convert(options.center)).sub(offset.div(scale)) : from,
around;
if (zoom !== startZoom) {
around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));
this.zooming = true;
}
if (startBearing !== bearing) {
this.rotating = true;
}
this.fire('movestart');
this._ease(function (k) {
if (zoom !== startZoom) {
tr.setZoomAround(interpolate(startZoom, zoom, k), around);
} else {
tr.center = tr.unproject(from.add(to.sub(from).mult(k)));
}
if (bearing !== startBearing) {
tr.bearing = interpolate(startBearing, bearing, k);
}
if (pitch !== startPitch) {
tr.pitch = interpolate(startPitch, pitch, k);
}
this.fire('move');
if (this.zooming) {
this.fire('zoom');
}
if (this.rotating) {
this.fire('rotate');
}
}, function() {
this.zooming = false;
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
/**
* Flying animation to a specified location/zoom/bearing with automatic curve
*
* @param {CameraOptions} options map view options
* @param {Number} [options.speed=1.2] How fast animation occurs
* @param {Number} [options.curve=1.42] How much zooming out occurs during animation
* @param {Function} [options.easing]
* @fires movestart
* @fires moveend
* @returns {this}
* @example
* // fly with default options to null island
* map.flyTo({center: [0, 0], zoom: 9});
* // using flyTo options
* map.flyTo({
* center: [0, 0],
* zoom: 9,
* speed: 0.2,
* curve: 1,
* easing: function(t) {
* return t;
* }
* });
*/
flyTo: function(options) {
this.stop();
options = util.extend({
offset: [0, 0],
speed: 1.2,
curve: 1.42,
easing: util.ease
}, options);
var tr = this.transform,
offset = Point.convert(options.offset),
startZoom = this.getZoom(),
startBearing = this.getBearing();
var center = 'center' in options ? LatLng.convert(options.center) : this.getCenter();
var zoom = 'zoom' in options ? +options.zoom : startZoom;
var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing;
var scale = tr.zoomScale(zoom - startZoom),
from = tr.point,
to = tr.project(center).sub(offset.div(scale));
var startWorldSize = tr.worldSize,
rho = options.curve,
V = options.speed,
w0 = Math.max(tr.width, tr.height),
w1 = w0 / scale,
u1 = to.sub(from).mag(),
rho2 = rho * rho;
function r(i) {
var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
return Math.log(Math.sqrt(b * b + 1) - b);
}
function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
function tanh(n) { return sinh(n) / cosh(n); }
var r0 = r(0),
w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },
u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },
S = (r(1) - r0) / rho;
if (Math.abs(u1) < 0.000001) {
if (Math.abs(w0 - w1) < 0.000001) return this;
var k = w1 < w0 ? -1 : 1;
S = Math.abs(Math.log(w1 / w0)) / rho;
u = function() { return 0; };
w = function(s) { return Math.exp(k * rho * s); };
}
options.duration = 1000 * S / V;
this.zooming = true;
if (startBearing !== bearing) this.rotating = true;
this.fire('movestart');
this._ease(function (k) {
var s = k * S,
us = u(s);
tr.zoom = startZoom + tr.scaleZoom(1 / w(s));
tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);
if (bearing !== startBearing) {
tr.bearing = interpolate(startBearing, bearing, k);
}
this.fire('move').fire('zoom');
if (bearing !== startBearing) {
this.fire('rotate');
}
}, function() {
this.zooming = false;
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
isEasing: function() {
return !!this._abortFn;
},
/**
* Stop current animation
*
* @returns {this}
*/
stop: function() {
if (this._abortFn) {
this._abortFn.call(this);
delete this._abortFn;
this._finishFn.call(this);
delete this._finishFn;
}
return this;
},
_ease: function(frame, finish, options) {
this._finishFn = finish;
this._abortFn = browser.timed(function (t) {
frame.call(this, options.easing(t));
if (t === 1) {
delete this._abortFn;
this._finishFn.call(this);
delete this._finishFn;
}
}, options.animate === false ? 0 : options.duration, this);
},
// convert bearing so that it's numerically close to the current one so that it interpolates properly
_normalizeBearing: function(bearing, currentBearing) {
bearing = util.wrap(bearing, -180, 180);
var diff = Math.abs(bearing - currentBearing);
if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;
if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;
return bearing;
},
_updateEasing: function(duration, zoom, bezier) {
var easing;
if (this.ease) {
var ease = this.ease,
t = (Date.now() - ease.start) / ease.duration,
speed = ease.easing(t + 0.01) - ease.easing(t),
// Quick hack to make new bezier that is continuous with last
x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,
y = Math.sqrt(0.27 * 0.27 - x * x);
easing = util.bezier(x, y, 0.25, 1);
} else {
easing = bezier ? util.bezier.apply(util, bezier) : util.ease;
}
// store information on current easing
this.ease = {
start: (new Date()).getTime(),
to: Math.pow(2, zoom),
duration: duration,
easing: easing
};
return easing;
}
});
},{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../util/browser":85,"../util/interpolate":92,"../util/util":96,"point-geometry":113}],75:[function(require,module,exports){
'use strict';
var Control = require('./control');
var DOM = require('../../util/dom');
var util = require('../../util/util');
module.exports = Attribution;
/**
* Creates an attribution control
* @class Attribution
* @example
* map.addControl(new mapboxgl.Attribution());
*/
function Attribution() {}
Attribution.prototype = util.inherit(Control, {
options: {
position: 'bottom-right'
},
onAdd: function(map) {
var className = 'mapboxgl-ctrl-attrib',
container = this._container = DOM.create('div', className, map.getContainer());
this._update();
map.on('source.load', this._update.bind(this));
map.on('source.change', this._update.bind(this));
map.on('source.remove', this._update.bind(this));
map.on('moveend', this._updateEditLink.bind(this));
return container;
},
_update: function() {
var attributions = [];
if (this._map.style) {
for (var id in this._map.style.sources) {
var source = this._map.style.sources[id];
if (source.attribution && attributions.indexOf(source.attribution) < 0) {
attributions.push(source.attribution);
}
}
}
this._container.innerHTML = attributions.join(' | ');
this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0];
this._updateEditLink();
},
_updateEditLink: function() {
if (this._editLink) {
var center = this._map.getCenter();
this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' +
center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1);
}
}
});
},{"../../util/dom":88,"../../util/util":96,"./control":76}],76:[function(require,module,exports){
'use strict';
module.exports = Control;
/**
* A base class for map-related interface elements.
*
* @class Control
*/
function Control() {}
Control.prototype = {
/**
* Add this control to the map, returning the control itself
* for chaining. This will insert the control's DOM element into
* the map's DOM element if the control has a `position` specified.
*
* @param {Map} map
* @returns {Control} this
*/
addTo: function(map) {
this._map = map;
var container = this._container = this.onAdd(map);
if (this.options && this.options.position) {
var pos = this.options.position;
var corner = map._controlCorners[pos];
container.className += ' mapboxgl-ctrl';
if (pos.indexOf('bottom') !== -1) {
corner.insertBefore(container, corner.firstChild);
} else {
corner.appendChild(container);
}
}
return this;
},
/**
* Remove this control from the map it has been added to.
*
* @returns {Control} this
*/
remove: function() {
this._container.parentNode.removeChild(this._container);
if (this.onRemove) this.onRemove(this._map);
this._map = null;
return this;
}
};
},{}],77:[function(require,module,exports){
'use strict';
var Control = require('./control');
var DOM = require('../../util/dom');
var util = require('../../util/util');
module.exports = Navigation;
/**
* Creates a navigation control with zoom buttons and a compass
* @class Navigation
* @param {Object} [options]
* @param {String} [options.position=top-right] A string indicating the control's position on the map. Options are `top-right`, `top-left`, `bottom-right`, `bottom-left`
* @example
* map.addControl(new mapboxgl.Navigation({position: 'top-left'})); // position is optional
*/
function Navigation(options) {
util.setOptions(this, options);
}
Navigation.prototype = util.inherit(Control, {
options: {
position: 'top-right'
},
onAdd: function(map) {
var className = 'mapboxgl-ctrl';
var container = this._container = DOM.create('div', className + '-group', map.getContainer());
this._zoomInButton = this._createButton(className + '-icon ' + className + '-zoom-in', map.zoomIn.bind(map));
this._zoomOutButton = this._createButton(className + '-icon ' + className + '-zoom-out', map.zoomOut.bind(map));
this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map));
var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass);
compassCanvas.style.cssText = 'width:30px; height:30px;';
compassCanvas.width = 26 * 2;
compassCanvas.height = 26 * 2;
this._compass.addEventListener('mousedown', this._onCompassDown.bind(this));
this._onCompassMove = this._onCompassMove.bind(this);
this._onCompassUp = this._onCompassUp.bind(this);
this._compassCtx = compassCanvas.getContext('2d');
map.on('rotate', this._drawNorth.bind(this));
this._drawNorth();
return container;
},
_onCompassDown: function(e) {
DOM.disableDrag();
document.addEventListener('mousemove', this._onCompassMove);
document.addEventListener('mouseup', this._onCompassUp);
this._prevX = e.screenX;
e.stopPropagation();
},
_onCompassMove: function(e) {
var x = e.screenX,
d = x < 2 ? -5 : // left edge of the screen, continue rotating
x > window.screen.width - 2 ? 5 : // right edge
(x - this._prevX) / 4;
this._map.setBearing(this._map.getBearing() - d);
this._prevX = e.screenX;
this._moved = true;
e.preventDefault();
},
_onCompassUp: function() {
document.removeEventListener('mousemove', this._onCompassMove);
document.removeEventListener('mouseup', this._onCompassUp);
DOM.enableDrag();
if (this._moved) {
this._moved = false;
DOM.suppressClick();
}
},
_createButton: function(className, fn) {
var a = DOM.create('button', className, this._container);
a.addEventListener('click', function() { fn(); });
return a;
},
_drawNorth: function() {
var rad = 20,
width = 8,
center = 26,
angle = this._map.transform.angle + (Math.PI / 2),
ctx = this._compassCtx;
this._compassCanvas.width = this._compassCanvas.width;
ctx.translate(center, center);
ctx.rotate(angle);
ctx.beginPath();
ctx.fillStyle = '#000';
ctx.lineTo(0, -width);
ctx.lineTo(-rad, 0);
ctx.lineTo(0, width);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = '#bbb';
ctx.moveTo(0, 0);
ctx.lineTo(0, width);
ctx.lineTo(rad, 0);
ctx.lineTo(0, -width);
ctx.fill();
ctx.beginPath();
ctx.strokeStyle = '#fff';
ctx.lineWidth = 4;
ctx.moveTo(0, -width);
ctx.lineTo(0, width);
ctx.stroke();
}
});
},{"../../util/dom":88,"../../util/util":96,"./control":76}],78:[function(require,module,exports){
'use strict';
var Interaction = require('./interaction');
var Point = require('point-geometry');
var util = require('../util/util');
var DOM = require('../util/dom');
var LatLngBounds = require('../geo/lat_lng_bounds');
module.exports = Handlers;
function Handlers(map) {
var rotateEnd;
var box;
var inertiaLinearity = 0.2,
inertiaEasing = util.bezier(0, 0, inertiaLinearity, 1);
function boxzoomFinish() {
if (box) {
box.parentNode.removeChild(box);
map.getContainer().classList.remove('mapboxgl-crosshair');
box = false;
DOM.enableDrag();
}
}
this.interaction = new Interaction(map.getCanvas())
.on('click', function(e) {
e.latLng = map.unproject(e.point);
map.fire('click', e);
})
.on('dblclick', function(e) {
e.latLng = map.unproject(e.point);
map.fire('dblclick', e);
})
.on('mousemove', function(e) {
e.latLng = map.unproject(e.point);
map.fire('mousemove', e);
})
.on('down', function() {
map.fire('movestart');
})
.on('resize', function() {
map.stop();
map.resize();
map.update();
})
.on('keydown', function(e) {
if (e.altKey || e.ctrlKey || e.metaKey) return;
var pan = 80;
var rotate = 2;
function zoomBy(z) {
map.zoomTo(Math.round(map.getZoom()) + (e.shiftKey ? 2 : 1) * z);
}
function panBy(v) {
map.panBy(v);
}
function rotateBy(v) {
map.setBearing(map.getBearing() + v);
}
switch (e.keyCode) {
case 61:
case 107:
case 171:
case 187:
zoomBy(1);
break;
case 189:
case 109:
case 173:
zoomBy(-1);
break;
case 37:
if (e.shiftKey) {
rotateBy(-rotate);
} else {
panBy([-pan, 0]);
}
break;
case 39:
if (e.shiftKey) {
rotateBy(rotate);
} else {
panBy([pan, 0]);
}
break;
case 38:
panBy([0, -pan]);
break;
case 40:
panBy([0, pan]);
break;
default:
return;
}
})
.on('pan', function(e) {
map.stop();
var mouseLocation = map.transform.pointLocation(e.point.add(e.offset));
map.transform.setLocationAtPoint(mouseLocation, e.point);
map.fire('move');
})
.on('panend', function(e) {
if (!e.inertia) {
map.fire('moveend');
} else {
// convert velocity to px/s & adjust for increased initial animation speed when easing out
var velocity = e.inertia.mult(1000 * inertiaLinearity),
speed = velocity.mag();
var maxSpeed = 4000; // px/s
if (speed >= maxSpeed) {
speed = maxSpeed;
velocity._unit()._mult(maxSpeed);
}
var deceleration = 8000, // px/s^2
duration = speed / (deceleration * inertiaLinearity),
offset = velocity.mult(-duration / 2).round();
map.panBy(offset, {
duration: duration * 1000,
easing: inertiaEasing,
noMoveStart: true
});
}
})
.on('zoom', function(e) {
// Scale by sigmoid of scroll wheel delta.
var scale = 2 / (1 + Math.exp(-Math.abs(e.delta / 100)));
if (e.delta < 0 && scale !== 0) scale = 1 / scale;
var fromScale = map.ease && isFinite(e.delta) ? map.ease.to : map.transform.scale,
duration = !isFinite(e.delta) ? 800 : 0;
map.zoomTo(map.transform.scaleZoom(fromScale * scale), {
duration: duration,
around: map.unproject(e.point)
});
})
.on('rotate', function(e) {
var center = map.transform.centerPoint, // Center of rotation
startToCenter = e.start.sub(center),
startToCenterDist = startToCenter.mag();
map.rotating = true;
// If the first click was too close to the center, move the center of rotation by 200 pixels
// in the direction of the click.
if (startToCenterDist < 200) {
center = e.start.add(new Point(-200, 0)._rotate(startToCenter.angle()));
}
var bearingDiff = e.prev.sub(center).angleWith(e.current.sub(center)) / Math.PI * 180;
map.transform.bearing = map.getBearing() - bearingDiff;
map.fire('move').fire('rotate');
window.clearTimeout(rotateEnd);
rotateEnd = window.setTimeout(function() {
map.rotating = false;
map._rerender();
}, 200);
})
.on('boxzoomstart', function(e) {
if (!box) {
box = DOM.create('div', 'mapboxgl-boxzoom', map.getContainer());
map.getContainer().classList.add('mapboxgl-crosshair');
map.fire('boxzoomstart');
DOM.disableDrag();
}
var minX = Math.min(e.start.x, e.current.x);
var maxX = Math.max(e.start.x, e.current.x);
var minY = Math.min(e.start.y, e.current.y);
var maxY = Math.max(e.start.y, e.current.y);
DOM.setTransform(box, 'translate(' + minX + 'px,' + minY + 'px)');
box.style.width = (maxX - minX) + 'px';
box.style.height = (maxY - minY) + 'px';
})
.on('boxzoomend', function(e) {
boxzoomFinish();
var bounds = new LatLngBounds(
map.unproject(e.start),
map.unproject(e.current)
);
map.fitBounds(bounds, { linear: true }).fire('boxzoomend', {
boxZoomBounds: bounds
});
})
.on('boxzoomcancel', boxzoomFinish);
}
},{"../geo/lat_lng_bounds":19,"../util/dom":88,"../util/util":96,"./interaction":80,"point-geometry":113}],79:[function(require,module,exports){
'use strict';
/*
* Adds positional coordinates to URL hashes. Passed as an option to the map object
*
* @class mapboxgl.Hash
* @returns {Hash} `this`
*/
module.exports = Hash;
var util = require('../util/util');
function Hash() {
util.bindAll([
'_onHashChange',
'_updateHash'
], this);
}
Hash.prototype = {
/* Map element to listen for coordinate changes
*
* @param {Object} map
* @returns {Hash} `this`
*/
addTo: function(map) {
this._map = map;
window.addEventListener('hashchange', this._onHashChange, false);
this._map.on('moveend', this._updateHash);
return this;
},
/* Removes hash
*
* @returns {Popup} `this`
*/
remove: function() {
window.removeEventListener('hashchange', this._onHashChange, false);
this._map.off('moveend', this._updateHash);
delete this._map;
return this;
},
_onHashChange: function() {
var loc = location.hash.replace('#', '').split('/');
if (loc.length >= 3) {
this._map.jumpTo({
center: [+loc[1], +loc[2]],
zoom: +loc[0],
bearing: +(loc[3] || 0)
});
return true;
}
return false;
},
_updateHash: function() {
var center = this._map.getCenter(),
zoom = this._map.getZoom(),
bearing = this._map.getBearing(),
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
hash = '#' + (Math.round(zoom * 100) / 100) +
'/' + center.lat.toFixed(precision) +
'/' + center.lng.toFixed(precision) +
(bearing ? '/' + (Math.round(bearing * 10) / 10) : '');
window.history.replaceState('', '', hash);
}
};
},{"../util/util":96}],80:[function(require,module,exports){
'use strict';
var Evented = require('../util/evented');
var browser = require('../util/browser');
var Point = require('point-geometry');
module.exports = Interaction;
/**
* Mouse event
*
* @event Map#mousemove
* @type {Object}
* @property {Point} point the pixel location of the event
* @property {Event} originalEvent the original DOM event
*/
/**
* Double click event.
*
* @event Map#dblclick
* @type {Object}
* @property {Point} point the pixel location of the event
*/
/**
* Pan event
*
* @event Map#pan
* @type {Object}
* @property {Point} point the pixel location of the event
* @property {Point} offset a point representing the movement from the previous map location to the current one.
*/
/**
* Pan end event
*
* @event Map#panend
* @type {Object}
* @property {number} velocity a measure of how much inertia was recorded in this pan motion
*/
function Interaction(el) {
var interaction = this;
if (!el) return;
var rotating = false,
panned = false,
boxzoom = false,
firstPos = null,
pos = null,
inertia = null,
now;
function mousePos(e) {
var rect = el.getBoundingClientRect();
return new Point(
e.clientX - rect.left - el.clientLeft,
e.clientY - rect.top - el.clientTop);
}
el.addEventListener('contextmenu', function(ev) {
rotating = true;
firstPos = pos = mousePos(ev);
ev.preventDefault();
}, false);
el.addEventListener('mousedown', onmousedown, false);
document.addEventListener('mouseup', onmouseup, false);
document.addEventListener('mousemove', onmousemove, false);
el.addEventListener('click', onclick, false);
scrollwheel(zoom);
el.addEventListener('dblclick', ondoubleclick, false);
window.addEventListener('resize', resize, false);
el.addEventListener('keydown', keydown, false);
function zoom(type, delta, point) {
interaction.fire('zoom', {
source: type,
delta: delta,
point: point
});
inertia = null;
now = null;
}
function click(point, ev) {
interaction.fire('click', {point: point, originalEvent: ev});
}
function mousemove(point, ev) {
interaction.fire('mousemove', {point: point, originalEvent: ev});
}
function pan(point) {
if (pos) {
var offset = pos.sub(point);
interaction.fire('pan', {offset: offset, point: point});
// add an averaged version of this movement to the inertia vector
if (inertia) {
var duration = Date.now() - now;
// sometimes it's 0 after some erratic paning
if (duration) {
var time = duration + now;
inertia.push([time, point]);
while (inertia.length > 2 && time - inertia[0][0] > 100) inertia.shift();
}
} else {
inertia = [];
}
now = Date.now();
pos = point;
}
}
function resize() {
interaction.fire('resize');
}
function keydown(ev) {
if (boxzoom && ev.keyCode === 27) {
interaction.fire('boxzoomcancel');
boxzoom = false;
}
interaction.fire('keydown', ev);
}
function rotate(point) {
if (pos) {
interaction.fire('rotate', {
start: firstPos,
prev: pos,
current: point
});
pos = point;
}
}
function doubleclick(point, ev) {
interaction.fire('dblclick', {
point: point,
originalEvent: ev
});
}
function onmousedown(ev) {
firstPos = pos = mousePos(ev);
interaction.fire('down');
if (ev.shiftKey || ((ev.which === 1) && (ev.button === 1))) {
boxzoom = true;
}
}
function onmouseup(ev) {
panned = pos && firstPos && (pos.x !== firstPos.x || pos.y !== firstPos.y);
rotating = false;
pos = null;
if (boxzoom) {
interaction.fire('boxzoomend', {
start: firstPos,
current: mousePos(ev)
});
boxzoom = false;
} else if (inertia && inertia.length >= 2 && now > Date.now() - 100) {
var last = inertia[inertia.length - 1],
first = inertia[0],
velocity = last[1].sub(first[1]).div(last[0] - first[0]);
interaction.fire('panend', {inertia: velocity});
} else if (pos) {
interaction.fire('panend');
}
inertia = null;
now = null;
}
function onmousemove(ev) {
var point = mousePos(ev);
if (boxzoom) {
interaction.fire('boxzoomstart', {
start: firstPos,
current: point
});
} else if (rotating) {
rotate(point);
} else if (pos) {
pan(point);
} else {
var target = ev.toElement || ev.target;
while (target && target !== el && target.parentNode) target = target.parentNode;
if (target === el) {
mousemove(point, ev);
}
}
}
function onclick(ev) {
if (!panned) click(mousePos(ev), ev);
}
function ondoubleclick(ev) {
doubleclick(mousePos(ev), ev);
zoom('wheel', Infinity * (ev.shiftKey ? -1 : 1), mousePos(ev));
ev.preventDefault();
}
function scrollwheel(callback) {
var firefox = /Firefox/i.test(navigator.userAgent);
var safari = /Safari/i.test(navigator.userAgent) && !/Chrom(ium|e)/i.test(navigator.userAgent);
var time = window.performance || Date;
el.addEventListener('wheel', wheel, false);
el.addEventListener('mousewheel', mousewheel, false);
var lastEvent = 0;
var type = null;
var typeTimeout = null;
var initialValue = null;
function scroll(value, ev) {
var stamp = time.now();
var timeDelta = stamp - lastEvent;
lastEvent = stamp;
var point = mousePos(ev);
if (value !== 0 && (value % 4.000244140625) === 0) {
// This one is definitely a mouse wheel event.
type = 'wheel';
// Normalize this value to match trackpad.
value = Math.floor(value / 4);
} else if (value !== 0 && Math.abs(value) < 4) {
// This one is definitely a trackpad event because it is so small.
type = 'trackpad';
} else if (timeDelta > 400) {
// This is likely a new scroll action.
type = null;
initialValue = value;
// Start a timeout in case this was a singular event, and dely it
// by up to 40ms.
typeTimeout = setTimeout(function() {
type = 'wheel';
callback(type, -initialValue, point);
}, 40);
} else if (type === null) {
// This is a repeating event, but we don't know the type of event
// just yet. If the delta per time is small, we assume it's a
// fast trackpad; otherwise we switch into wheel mode.
type = (Math.abs(timeDelta * value) < 200) ? 'trackpad' : 'wheel';
// Make sure our delayed event isn't fired again, because we
// accumulate the previous event (which was less than 40ms ago) into
// this event.
if (typeTimeout) {
clearTimeout(typeTimeout);
typeTimeout = null;
value += initialValue;
}
}
// Slow down zoom if shift key is held for more precise zooming
if (ev.shiftKey && value) value = value / 4;
// Only fire the callback if we actually know what type of scrolling
// device the user uses.
if (type !== null) {
callback(type, -value, point);
}
}
function wheel(e) {
var deltaY = e.deltaY;
// Firefox doubles the values on retina screens...
if (firefox && e.deltaMode === window.WheelEvent.DOM_DELTA_PIXEL) deltaY /= browser.devicePixelRatio;
if (e.deltaMode === window.WheelEvent.DOM_DELTA_LINE) deltaY *= 40;
scroll(deltaY, e);
e.preventDefault();
}
function mousewheel(e) {
var deltaY = -e.wheelDeltaY;
if (safari) deltaY = deltaY / 3;
scroll(deltaY, e);
e.preventDefault();
}
}
}
Interaction.prototype = Object.create(Evented);
},{"../util/browser":85,"../util/evented":90,"point-geometry":113}],81:[function(require,module,exports){
'use strict';
var Canvas = require('../util/canvas');
var util = require('../util/util');
var browser = require('../util/browser');
var Evented = require('../util/evented');
var DOM = require('../util/dom');
var Style = require('../style/style');
var AnimationLoop = require('../style/animation_loop');
var Painter = require('../render/painter');
var Transform = require('../geo/transform');
var Hash = require('./hash');
var Handlers = require('./handlers');
var Camera = require('./camera');
var LatLng = require('../geo/lat_lng');
var LatLngBounds = require('../geo/lat_lng_bounds');
var Point = require('point-geometry');
var Attribution = require('./control/attribution');
/**
* Creates a map instance.
* @class Map
* @param {Object} options
* @param {String} options.container HTML element to initialize the map in (or element id as string)
* @param {Number} [options.minZoom=0] Minimum zoom of the map
* @param {Number} [options.maxZoom=20] Maximum zoom of the map
* @param {Object} options.style Map style and data source definition (either a JSON object or a JSON URL), described in the [style reference](https://mapbox.com/mapbox-gl-style-spec/)
* @param {Boolean} [options.hash=false] If `true`, the map will track and update the page URL according to map position
* @param {Boolean} [options.interactive=true] If `false`, no mouse, touch, or keyboard listeners are attached to the map, so it will not respond to input
* @param {Array} options.classes Style class names with which to initialize the map
* @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.
* @param {Boolean} [options.preserveDrawingBuffer=false] If `true`, The maps canvas can be exported to a PNG using `map.getCanvas().toDataURL();`. This is false by default as a performance optimization.
* @example
* var map = new mapboxgl.Map({
* container: 'map',
* center: [37.772537, -122.420679],
* zoom: 13,
* style: style_object,
* hash: true
* });
*/
var Map = module.exports = function(options) {
options = this.options = util.inherit(this.options, options);
this.animationLoop = new AnimationLoop();
this.transform = new Transform(options.minZoom, options.maxZoom);
if (options.maxBounds) {
var b = LatLngBounds.convert(options.maxBounds);
this.transform.latRange = [b.getSouth(), b.getNorth()];
this.transform.lngRange = [b.getWest(), b.getEast()];
}
util.bindAll([
'_forwardStyleEvent',
'_forwardSourceEvent',
'_forwardLayerEvent',
'_forwardTileEvent',
'_onStyleLoad',
'_onStyleChange',
'_onSourceAdd',
'_onSourceRemove',
'_onSourceUpdate',
'update',
'render'
], this);
this._setupContainer();
this._setupPainter();
this.on('move', this.update);
this.on('zoom', this.update.bind(this, true));
this.on('moveend', function() {
this.animationLoop.set(300); // text fading
this._rerender();
}.bind(this));
this.handlers = options.interactive && new Handlers(this);
this._hash = options.hash && (new Hash()).addTo(this);
// don't set position from options if set through hash
if (!this._hash || !this._hash._onHashChange()) {
this.jumpTo(options);
}
this.sources = {};
this.stacks = {};
this._classes = {};
this.resize();
if (options.classes) this.setClasses(options.classes);
if (options.style) this.setStyle(options.style);
if (options.attributionControl) this.addControl(new Attribution());
};
util.extend(Map.prototype, Evented);
util.extend(Map.prototype, Camera.prototype);
util.extend(Map.prototype, /** @lends Map.prototype */{
options: {
center: [0, 0],
zoom: 0,
bearing: 0,
pitch: 0,
minZoom: 0,
maxZoom: 20,
interactive: true,
hash: false,
attributionControl: true,
failIfMajorPerformanceCaveat: false,
preserveDrawingBuffer: false
},
addControl: function(control) {
control.addTo(this);
return this;
},
/**
* @typedef {Object} [styleOptions]
* @param {Boolean} [styleOptions.transition=true]
*/
/**
* Adds a style class to a map
*
* @param {string} klass name of style class
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
addClass: function(klass, options) {
if (this._classes[klass]) return;
this._classes[klass] = true;
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Removes a style class from a map
*
* @param {string} klass name of style class
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
removeClass: function(klass, options) {
if (!this._classes[klass]) return;
delete this._classes[klass];
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Helper method to add more than one class
*
* @param {Array<string>} klasses An array of class names
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
setClasses: function(klasses, options) {
this._classes = {};
for (var i = 0; i < klasses.length; i++) {
this._classes[klasses[i]] = true;
}
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Check whether a style class is active
*
* @param {string} klass Name of style class
* @returns {boolean}
*/
hasClass: function(klass) {
return !!this._classes[klass];
},
/**
* Return an array of the current active style classes
*
* @returns {boolean}
*/
getClasses: function() {
return Object.keys(this._classes);
},
/**
* Detect the map's new width and height and resize it.
*
* @returns {Map} `this`
*/
resize: function() {
var width = 0, height = 0;
if (this._container) {
width = this._container.offsetWidth || 400;
height = this._container.offsetHeight || 300;
}
this._canvas.resize(width, height);
this.transform.width = width;
this.transform.height = height;
this.transform._constrain();
this.painter.resize(width, height);
return this
.fire('movestart')
.fire('move')
.fire('resize')
.fire('moveend');
},
/**
* Get the map's geographical bounds
*
* @returns {LatLngBounds}
*/
getBounds: function() {
return new LatLngBounds(
this.transform.pointLocation(new Point(0, 0)),
this.transform.pointLocation(this.transform.size));
},
/**
* Get pixel coordinates (relative to map container) given a geographical location
*
* @param {LatLng} latlng
* @returns {Object} `x` and `y` coordinates
*/
project: function(latlng) {
return this.transform.locationPoint(LatLng.convert(latlng));
},
/**
* Get geographical coordinates given pixel coordinates
*
* @param {Array<number>} point [x, y] pixel coordinates
* @returns {LatLng}
*/
unproject: function(point) {
return this.transform.pointLocation(Point.convert(point));
},
/**
* Get all features at a point ([x, y])
*
* @param {Array<number>} point [x, y] pixel coordinates
* @param {Object} params
* @param {number} [params.radius=0] Optional. Radius in pixels to search in
* @param {string} params.layer Optional. Only return features from a given layer
* @param {string} params.type Optional. Either `raster` or `vector`
* @param {featuresAtCallback} callback function that returns the response
*
* @callback featuresAtCallback
* @param {Object|null} err Error _If any_
* @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`
*
* @returns {Map} `this`
*
* @example
* map.featuresAt([10, 20], { radius: 10 }, function(err, features) {
* console.log(features);
* });
*/
featuresAt: function(point, params, callback) {
var coord = this.transform.pointCoordinate(Point.convert(point));
this.style.featuresAt(coord, params, callback);
return this;
},
/**
* Replaces the map's style object
*
* @param {Object} style A style object formatted as JSON
* @returns {Map} `this`
*/
setStyle: function(style) {
if (this.style) {
this.style
.off('load', this._onStyleLoad)
.off('error', this._forwardStyleEvent)
.off('change', this._onStyleChange)
.off('source.add', this._onSourceAdd)
.off('source.remove', this._onSourceRemove)
.off('source.load', this._onSourceUpdate)
.off('source.error', this._forwardSourceEvent)
.off('source.change', this._onSourceUpdate)
.off('layer.add', this._forwardLayerEvent)
.off('layer.remove', this._forwardLayerEvent)
.off('tile.add', this._forwardTileEvent)
.off('tile.remove', this._forwardTileEvent)
.off('tile.load', this.update)
.off('tile.error', this._forwardTileEvent)
._remove();
this.off('rotate', this.style._redoPlacement);
this.off('pitch', this.style._redoPlacement);
}
if (!style) {
this.style = null;
return this;
} else if (style instanceof Style) {
this.style = style;
} else {
this.style = new Style(style, this.animationLoop);
}
this.style
.on('load', this._onStyleLoad)
.on('error', this._forwardStyleEvent)
.on('change', this._onStyleChange)
.on('source.add', this._onSourceAdd)
.on('source.remove', this._onSourceRemove)
.on('source.load', this._onSourceUpdate)
.on('source.error', this._forwardSourceEvent)
.on('source.change', this._onSourceUpdate)
.on('layer.add', this._forwardLayerEvent)
.on('layer.remove', this._forwardLayerEvent)
.on('tile.add', this._forwardTileEvent)
.on('tile.remove', this._forwardTileEvent)
.on('tile.load', this.update)
.on('tile.error', this._forwardTileEvent);
this.on('rotate', this.style._redoPlacement);
this.on('pitch', this.style._redoPlacement);
return this;
},
/**
* Add a source to the map style.
*
* @param {string} id ID of the source. Must not be used by any existing source.
* @param {Object} source source specification, following the
* [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)
* @fires source.add
* @returns {Map} `this`
*/
addSource: function(id, source) {
this.style.addSource(id, source);
return this;
},
/**
* Remove an existing source from the map style.
*
* @param {string} id ID of the source to remove
* @fires source.remove
* @returns {Map} `this`
*/
removeSource: function(id) {
this.style.removeSource(id);
return this;
},
/**
* Return the style source object with the given `id`.
*
* @param {string} id source ID
* @returns {Object}
*/
getSource: function(id) {
return this.style.getSource(id);
},
/**
* Add a layer to the map style. The layer will be inserted before the layer with
* ID `before`, or appended if `before` is omitted.
* @param {StyleLayer|Object} layer
* @param {string=} before ID of an existing layer to insert before
* @fires layer.add
* @returns {Map} `this`
*/
addLayer: function(layer, before) {
this.style.addLayer(layer, before);
this.style._cascade(this._classes);
return this;
},
/**
* Remove the layer with the given `id` from the map. Any layers which refer to the
* specified layer via a `ref` property are also removed.
*
* @param {string} id layer id
* @fires layer.remove
* @returns {Map} this
*/
removeLayer: function(id) {
this.style.removeLayer(id);
this.style._cascade(this._classes);
return this;
},
/**
* Set the filter for a given style layer.
*
* @param {string} layer ID of a layer
* @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)
* @returns {Map} `this`
*/
setFilter: function(layer, filter) {
this.style.setFilter(layer, filter);
return this;
},
/**
* Get the filter for a given style layer.
*
* @param {string} layer ID of a layer
* @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)
*/
getFilter: function(layer) {
return this.style.getFilter(layer);
},
/**
* Set the value of a paint property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a paint property
* @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)
* @param {string=} klass optional class specifier for the property
* @returns {Map} `this`
*/
setPaintProperty: function(layer, name, value, klass) {
this.style.setPaintProperty(layer, name, value, klass);
this.style._cascade(this._classes);
this.update(true);
return this;
},
/**
* Get the value of a paint property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a paint property
* @param {string=} klass optional class specifier for the property
* @returns {*} value for the paint propery
*/
getPaintProperty: function(layer, name, klass) {
return this.style.getPaintProperty(layer, name, klass);
},
/**
* Set the value of a layout property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a layout property
* @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)
* @returns {Map} `this`
*/
setLayoutProperty: function(layer, name, value) {
this.style.setLayoutProperty(layer, name, value);
return this;
},
/**
* Get the value of a layout property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a layout property
* @param {string=} klass optional class specifier for the property
* @returns {*} value for the layout propery
*/
getLayoutProperty: function(layer, name) {
return this.style.getLayoutProperty(layer, name);
},
/**
* Get the Map's container as an HTML element
* @returns {HTMLElement} container
*/
getContainer: function() {
return this._container;
},
/**
* Get the container for the map `canvas` element.
*
* If you want to add non-GL overlays to the map, you should append them to this element. This
* is the element to which event bindings for map interactivity such as panning and zooming are
* attached. It will receive bubbled events for child elements such as the `canvas`, but not for
* map controls.
*
* @returns {HTMLElement} container
*/
getCanvasContainer: function() {
return this._canvasContainer;
},
/**
* Get the Map's canvas as an HTML canvas
* @returns {HTMLElement} canvas
*/
getCanvas: function() {
return this._canvas.getElement();
},
_setupContainer: function() {
var id = this.options.container;
var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;
container.classList.add('mapboxgl-map');
var canvasContainer = this._canvasContainer = DOM.create('div', 'mapboxgl-canvas-container', container);
if (this.options.interactive) {
canvasContainer.classList.add('mapboxgl-interactive');
}
this._canvas = new Canvas(this, canvasContainer);
var controlContainer = DOM.create('div', 'mapboxgl-control-container', container);
var corners = this._controlCorners = {};
['top-left', 'top-right', 'bottom-left', 'bottom-right'].forEach(function (pos) {
corners[pos] = DOM.create('div', 'mapboxgl-ctrl-' + pos, controlContainer);
});
},
_setupPainter: function() {
var gl = this._canvas.getWebGLContext({
failIfMajorPerformanceCaveat: this.options.failIfMajorPerformanceCaveat,
preserveDrawingBuffer: this.options.preserveDrawingBuffer
});
if (!gl) {
console.error('Failed to initialize WebGL');
return;
}
this.painter = new Painter(gl, this.transform);
},
_contextLost: function(event) {
event.preventDefault();
if (this._frameId) {
browser.cancelFrame(this._frameId);
}
},
_contextRestored: function() {
this._setupPainter();
this.resize();
this.update();
},
/**
* Is this map fully loaded? If the style isn't loaded
* or it has a change to the sources or style that isn't
* propagated to its style, return false.
*
* @returns {boolean} whether the map is loaded
*/
loaded: function() {
if (this._styleDirty || this._sourcesDirty)
return false;
if (this.style && !this.style.loaded())
return false;
return true;
},
/**
* Update this map's style and re-render the map.
*
* @param {Object} updateStyle new style
* @returns {Map} this
*/
update: function(updateStyle) {
if (!this.style) return this;
this._styleDirty = this._styleDirty || updateStyle;
this._sourcesDirty = true;
this._rerender();
return this;
},
/**
* Call when a (re-)render of the map is required, e.g. when the
* user panned or zoomed,f or new data is available.
* @returns {Map} this
*/
render: function() {
if (this.style && this._styleDirty) {
this._styleDirty = false;
this.style._recalculate(this.transform.zoom);
}
if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {
this._sourcesDirty = false;
this._sourcesDirtyTimeout = setTimeout(function() {
this._sourcesDirtyTimeout = null;
}.bind(this), 50);
this.style._updateSources(this.transform);
}
this.painter.render(this.style, {
debug: this.debug,
vertices: this.vertices,
rotating: this.rotating,
zooming: this.zooming
});
this.fire('render');
if (this.loaded() && !this._loaded) {
this._loaded = true;
this.fire('load');
}
this._frameId = null;
if (!this.animationLoop.stopped()) {
this._styleDirty = true;
}
if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {
this._rerender();
}
return this;
},
/**
* Destroys the map's underlying resources, including web workers.
* @returns {Map} this
*/
remove: function() {
if (this._hash) this._hash.remove();
browser.cancelFrame(this._frameId);
clearTimeout(this._sourcesDirtyTimeout);
this.setStyle(null);
return this;
},
_rerender: function() {
if (this.style && !this._frameId) {
this._frameId = browser.frame(this.render);
}
},
_forwardStyleEvent: function(e) {
this.fire('style.' + e.type, util.extend({style: e.target}, e));
},
_forwardSourceEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_forwardLayerEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_forwardTileEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_onStyleLoad: function(e) {
this.style._cascade(this._classes, {transition: false});
this._forwardStyleEvent(e);
},
_onStyleChange: function(e) {
this.update(true);
this._forwardStyleEvent(e);
},
_onSourceAdd: function(e) {
var source = e.source;
if (source.onAdd)
source.onAdd(this);
this._forwardSourceEvent(e);
},
_onSourceRemove: function(e) {
var source = e.source;
if (source.onRemove)
source.onRemove(this);
this._forwardSourceEvent(e);
},
_onSourceUpdate: function(e) {
this.update();
this._forwardSourceEvent(e);
}
});
util.extendAll(Map.prototype, {
/**
* Enable debugging mode
*
* @name debug
* @memberof Map
* @type {boolean}
*/
_debug: false,
get debug() { return this._debug; },
set debug(value) { this._debug = value; this.update(); },
/**
* Show collision boxes: useful for debugging label placement
* in styles.
*
* @name collisionDebug
* @memberof Map
* @type {boolean}
*/
_collisionDebug: false,
get collisionDebug() { return this._collisionDebug; },
set collisionDebug(value) {
this._collisionDebug = value;
for (var i in this.style.sources) {
if (this.style.sources[i].reload) {
this.style.sources[i].reload();
}
}
this.update();
},
/**
* Enable continuous repaint to analyze performance
*
* @name repaint
* @memberof Map
* @type {boolean}
*/
_repaint: false,
get repaint() { return this._repaint; },
set repaint(value) { this._repaint = value; this.update(); },
// show vertices
_vertices: false,
get vertices() { return this._vertices; },
set vertices(value) { this._vertices = value; this.update(); }
});
},{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../geo/transform":20,"../render/painter":34,"../style/animation_loop":47,"../style/style":52,"../util/browser":85,"../util/canvas":86,"../util/dom":88,"../util/evented":90,"../util/util":96,"./camera":74,"./control/attribution":75,"./handlers":78,"./hash":79,"point-geometry":113}],82:[function(require,module,exports){
'use strict';
module.exports = Popup;
var util = require('../util/util');
var Evented = require('../util/evented');
var DOM = require('../util/dom');
var LatLng = require('../geo/lat_lng');
/**
* Creates a popup component
* @class Popup
* @param {Object} options
* @param {Boolean} options.closeButton
* @param {Boolean} options.closeOnClick
* @example
* var tooltip = new mapboxgl.Popup()
* .setLatLng(map.unproject(e.point))
* .setHTML("<h1>Hello World!</h1>")
* .addTo(map);
*/
function Popup(options) {
util.setOptions(this, options);
util.bindAll([
'_updatePosition',
'_onClickClose'],
this);
}
Popup.prototype = util.inherit(Evented, /** @lends Popup.prototype */{
options: {
closeButton: true,
closeOnClick: true
},
/**
* Attaches the popup to a map
* @param {Map} map
* @returns {Popup} `this`
*/
addTo: function(map) {
this._map = map;
this._map.on('move', this._updatePosition);
if (this.options.closeOnClick) {
this._map.on('click', this._onClickClose);
}
this._update();
return this;
},
/**
* Removes the popup from the map
* @example
* var popup = new mapboxgl.Popup().addTo(map);
* popup.remove();
* @returns {Popup} `this`
*/
remove: function() {
if (this._container) {
this._container.parentNode.removeChild(this._container);
}
if (this._map) {
this._map.off('move', this._updatePosition);
this._map.off('click', this._onClickClose);
delete this._map;
}
return this;
},
/**
* Get the current coordinates of popup element relative to map
* @returns {LatLng}
*/
getLatLng: function() {
return this._latLng;
},
/**
* Set the coordinates of a popup element to a map
* @param {LatLng} latlng
* @returns {Popup} `this`
*/
setLatLng: function(latlng) {
this._latLng = LatLng.convert(latlng);
this._update();
return this;
},
/**
* Fill a popup element with text only content
* @param {string} text
* @returns {Popup} `this`
*/
setText: function(text) {
this._content = document.createTextNode(text);
this._updateContent();
return this;
},
/**
* Fill a popup element with HTML content
* @param {string} html
* @returns {Popup} `this`
*/
setHTML: function(html) {
this._content = document.createDocumentFragment();
var temp = document.createElement('body'), child;
temp.innerHTML = html;
while (true) {
child = temp.firstChild;
if (!child) break;
this._content.appendChild(child);
}
this._updateContent();
return this;
},
_update: function() {
if (!this._map) { return; }
if (!this._container) {
this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());
this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);
this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);
if (this.options.closeButton) {
this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);
this._closeButton.innerHTML = '×';
this._closeButton.addEventListener('click', this._onClickClose);
}
}
this._updateContent();
this._updatePosition();
},
_updateContent: function() {
if (!this._content || !this._container) { return; }
var node = this._wrapper;
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
node.appendChild(this._closeButton);
node.appendChild(this._content);
},
_updatePosition: function() {
if (!this._latLng || !this._container) { return; }
var pos = this._map.project(this._latLng).round(),
anchor = this.options.anchor;
if (!anchor) {
var width = this._container.offsetWidth,
height = this._container.offsetHeight;
if (pos.y < height) {
anchor = ['top'];
} else if (pos.y > this._map.transform.height - height) {
anchor = ['bottom'];
} else {
anchor = [];
}
if (pos.x < width / 2) {
anchor.push('left');
} else if (pos.x > this._map.transform.width - width / 2) {
anchor.push('right');
}
if (anchor.length === 0) {
anchor = 'bottom';
} else {
anchor = anchor.join('-');
}
this.options.anchor = anchor;
}
var anchorTranslate = {
'top': 'translate(-50%,0)',
'top-left': 'translate(0,0)',
'top-right': 'translate(-100%,0)',
'bottom': 'translate(-50%,-100%)',
'bottom-left': 'translate(0,-100%)',
'bottom-right': 'translate(-100%,-100%)',
'left': 'translate(0,-50%)',
'right': 'translate(-100%,-50%)'
};
var classList = this._container.classList;
for (var key in anchorTranslate) {
classList.remove('mapboxgl-popup-anchor-' + key);
}
classList.add('mapboxgl-popup-anchor-' + anchor);
DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');
},
_onClickClose: function() {
this.remove();
}
});
},{"../geo/lat_lng":18,"../util/dom":88,"../util/evented":90,"../util/util":96}],83:[function(require,module,exports){
'use strict';
module.exports = Actor;
/**
* An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model)
* that maintains the relationship between asynchronous tasks and the objects
* that spin them off - in this case, tasks like parsing parts of styles,
* owned by the styles
*
* @param {WebWorker} target
* @param {WebWorker} parent
* @private
*/
function Actor(target, parent) {
this.target = target;
this.parent = parent;
this.callbacks = {};
this.callbackID = 0;
this.receive = this.receive.bind(this);
this.target.addEventListener('message', this.receive, false);
}
Actor.prototype.receive = function(message) {
var data = message.data,
callback;
if (data.type === '<response>') {
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
callback(data.error || null, data.data);
} else if (typeof data.id !== 'undefined') {
var id = data.id;
this.parent[data.type](data.data, function(err, data, buffers) {
this.postMessage({
type: '<response>',
id: String(id),
error: err ? String(err) : null,
data: data
}, buffers);
}.bind(this));
} else {
this.parent[data.type](data.data);
}
};
Actor.prototype.send = function(type, data, callback, buffers) {
var id = null;
if (callback) this.callbacks[id = this.callbackID++] = callback;
this.postMessage({ type: type, id: String(id), data: data }, buffers);
};
/**
* Wrapped postMessage API that abstracts around IE's lack of
* `transferList` support.
*
* @param {Object} message
* @param {Object} transferList
*/
Actor.prototype.postMessage = function(message, transferList) {
try {
this.target.postMessage(message, transferList);
} catch (e) {
this.target.postMessage(message); // No support for transferList on IE
}
};
},{}],84:[function(require,module,exports){
'use strict';
exports.getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onerror = function(e) {
callback(e);
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
var data;
try {
data = JSON.parse(xhr.response);
} catch (err) {
return callback(err);
}
callback(null, data);
} else {
callback(new Error(xhr.statusText));
}
};
xhr.send();
return xhr;
};
exports.getArrayBuffer = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onerror = function(e) {
callback(e);
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
callback(null, xhr.response);
} else {
callback(new Error(xhr.statusText));
}
};
xhr.send();
return xhr;
};
exports.getImage = function(url, callback) {
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function() {
callback(null, img);
};
img.src = url;
img.getData = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0);
return context.getImageData(0, 0, img.width, img.height).data;
};
return img;
};
exports.getVideo = function(urls, callback) {
var video = document.createElement('video');
video.crossOrigin = 'Anonymous';
video.onloadstart = function() {
callback(null, video);
};
for (var i = 0; i < urls.length; i++) {
var s = document.createElement('source');
s.src = urls[i];
video.appendChild(s);
}
video.getData = function() { return video; };
return video;
};
},{}],85:[function(require,module,exports){
'use strict';
var Canvas = require('./canvas');
var frame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
exports.frame = function(fn) {
return frame(fn);
};
var cancel = window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame;
exports.cancelFrame = function(id) {
cancel(id);
};
exports.timed = function (fn, dur, ctx) {
if (!dur) {
fn.call(ctx, 1);
return null;
}
var abort = false,
start = window.performance ? window.performance.now() : Date.now();
function tick(now) {
if (abort) return;
if (!window.performance) now = Date.now();
if (now >= start + dur) {
fn.call(ctx, 1);
} else {
fn.call(ctx, (now - start) / dur);
exports.frame(tick);
}
}
exports.frame(tick);
return function() { abort = true; };
};
/**
* Test whether the basic JavaScript and DOM features required for Mapbox GL are present.
* @param {Object} options
* @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.
* @return {Boolean} Returns true if Mapbox GL should be expected to work, and false if not.
*/
exports.supported = function(options) {
var supports = [
function() { return typeof window !== 'undefined'; },
function() { return typeof document !== 'undefined'; },
function () {
return !!(Array.prototype &&
Array.prototype.every &&
Array.prototype.filter &&
Array.prototype.forEach &&
Array.prototype.indexOf &&
Array.prototype.lastIndexOf &&
Array.prototype.map &&
Array.prototype.some &&
Array.prototype.reduce &&
Array.prototype.reduceRight &&
Array.isArray);
},
function() {
return !!(Function.prototype && Function.prototype.bind) &&
!!(Object.keys &&
Object.create &&
Object.getPrototypeOf &&
Object.getOwnPropertyNames &&
Object.isSealed &&
Object.isFrozen &&
Object.isExtensible &&
Object.getOwnPropertyDescriptor &&
Object.defineProperty &&
Object.defineProperties &&
Object.seal &&
Object.freeze &&
Object.preventExtensions);
},
function() {
return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON;
},
function() {
return new Canvas().supportsWebGLContext((options && options.failIfMajorPerformanceCaveat) || false);
},
function() { return 'Worker' in window; }
];
for (var i = 0; i < supports.length; i++) {
if (!supports[i]()) return false;
}
return true;
};
exports.hardwareConcurrency = navigator.hardwareConcurrency || 8;
Object.defineProperty(exports, 'devicePixelRatio', {
get: function() { return window.devicePixelRatio; }
});
},{"./canvas":86}],86:[function(require,module,exports){
'use strict';
var util = require('../util');
module.exports = Canvas;
function Canvas(parent, container) {
this.canvas = document.createElement('canvas');
if (parent && container) {
this.canvas.style.position = 'absolute';
this.canvas.classList.add('mapboxgl-canvas');
this.canvas.addEventListener('webglcontextlost', parent._contextLost.bind(parent), false);
this.canvas.addEventListener('webglcontextrestored', parent._contextRestored.bind(parent), false);
this.canvas.setAttribute('tabindex', 0);
container.appendChild(this.canvas);
}
}
Canvas.prototype.resize = function(width, height) {
var pixelRatio = window.devicePixelRatio || 1;
// Request the required canvas size taking the pixelratio into account.
this.canvas.width = pixelRatio * width;
this.canvas.height = pixelRatio * height;
// Maintain the same canvas size, potentially downscaling it for HiDPI displays
this.canvas.style.width = width + 'px';
this.canvas.style.height = height + 'px';
};
var requiredContextAttributes = {
antialias: false,
alpha: true,
stencil: true,
depth: false
};
Canvas.prototype.getWebGLContext = function(attributes) {
attributes = util.extend({}, attributes, requiredContextAttributes);
return this.canvas.getContext('webgl', attributes) ||
this.canvas.getContext('experimental-webgl', attributes);
};
Canvas.prototype.supportsWebGLContext = function(failIfMajorPerformanceCaveat) {
var attributes = util.extend({
failIfMajorPerformanceCaveat: failIfMajorPerformanceCaveat
}, requiredContextAttributes);
if ('probablySupportsContext' in this.canvas) {
return this.canvas.probablySupportsContext('webgl', attributes) ||
this.canvas.probablySupportsContext('experimental-webgl', attributes);
} else if ('supportsContext' in this.canvas) {
return this.canvas.supportsContext('webgl', attributes) ||
this.canvas.supportsContext('experimental-webgl', attributes);
}
return !!window.WebGLRenderingContext && !!this.getWebGLContext(failIfMajorPerformanceCaveat);
};
Canvas.prototype.getElement = function() {
return this.canvas;
};
},{"../util":96}],87:[function(require,module,exports){
'use strict';
var Actor = require('../actor');
var WebWorkify = require('webworkify');
module.exports = Dispatcher;
function Dispatcher(length, parent) {
this.actors = [];
this.currentActor = 0;
for (var i = 0; i < length; i++) {
var worker = new WebWorkify(require('../../source/worker'));
var actor = new Actor(worker, parent);
actor.name = "Worker " + i;
this.actors.push(actor);
}
}
Dispatcher.prototype = {
broadcast: function(type, data) {
for (var i = 0; i < this.actors.length; i++) {
this.actors[i].send(type, data);
}
},
send: function(type, data, callback, targetID, buffers) {
if (typeof targetID !== 'number' || isNaN(targetID)) {
// Use round robin to send requests to web workers.
targetID = this.currentActor = (this.currentActor + 1) % this.actors.length;
}
this.actors[targetID].send(type, data, callback, buffers);
return targetID;
},
remove: function() {
for (var i = 0; i < this.actors.length; i++) {
this.actors[i].target.terminate();
}
this.actors = [];
}
};
},{"../../source/worker":45,"../actor":83,"webworkify":125}],88:[function(require,module,exports){
'use strict';
exports.create = function (tagName, className, container) {
var el = document.createElement(tagName);
if (className) el.className = className;
if (container) container.appendChild(el);
return el;
};
var docStyle = document.documentElement.style;
function testProp(props) {
for (var i = 0; i < props.length; i++) {
if (props[i] in docStyle) {
return props[i];
}
}
}
var selectProp = testProp(['userSelect', 'MozUserSelect', 'WebkitUserSelect', 'msUserSelect']),
userSelect;
exports.disableDrag = function () {
if (selectProp) {
userSelect = docStyle[selectProp];
docStyle[selectProp] = 'none';
}
};
exports.enableDrag = function () {
if (selectProp) {
docStyle[selectProp] = userSelect;
}
};
var transformProp = testProp(['transform', 'WebkitTransform']);
exports.setTransform = function(el, value) {
el.style[transformProp] = value;
};
// Suppress the next click, but only if it's immediate.
function suppressClick(e) {
e.preventDefault();
e.stopPropagation();
window.removeEventListener('click', suppressClick, true);
}
exports.suppressClick = function() {
window.addEventListener('click', suppressClick, true);
window.setTimeout(function() {
window.removeEventListener('click', suppressClick, true);
}, 0);
};
},{}],89:[function(require,module,exports){
'use strict';
module.exports = {
HTTP_URL: 'http://a.tiles.mapbox.com',
HTTPS_URL: 'https://a.tiles.mapbox.com',
FORCE_HTTPS: true,
REQUIRE_ACCESS_TOKEN: true
};
},{}],90:[function(require,module,exports){
'use strict';
var util = require('./util');
/**
* Methods mixed in to other classes for event capabilities.
* @mixin Evented
*/
var Evented = {
/**
* Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties
*
* @param {String} type Event type
* @param {Function} listener Function to be called when the event is fired
*/
on: function(type, fn) {
this._events = this._events || {};
this._events[type] = this._events[type] || [];
this._events[type].push(fn);
return this;
},
/**
* Remove a event listener
*
* @param {String} [type] Event type. If none is specified, remove all listeners
* @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed
*/
off: function(type, fn) {
if (!type) {
// clear all listeners if no arguments specified
delete this._events;
return this;
}
if (!this.listens(type)) return this;
if (fn) {
var idx = this._events[type].indexOf(fn);
if (idx >= 0) {
this._events[type].splice(idx, 1);
}
if (!this._events[type].length) {
delete this._events[type];
}
} else {
delete this._events[type];
}
return this;
},
/**
* Call a function once when an event has fired
*
* @param {String} type Event type.
* @param {Function} listener Function to be called once when the event is fired
*/
once: function(type, fn) {
var wrapper = function(data) {
this.off(type, wrapper);
fn.call(this, data);
}.bind(this);
this.on(type, wrapper);
return this;
},
/**
* Fire event of a given string type with the given data object
*
* @param {String} type The event name
* @param {Object} [data] Optional data passed down to the event object
* @returns {Boolean} Returns true if the object listens to an event of a particular type
*/
fire: function(type, data) {
if (!this.listens(type)) return this;
data = util.extend({}, data);
util.extend(data, {type: type, target: this});
// make sure adding/removing listeners inside other listeners won't cause infinite loop
var listeners = this._events[type].slice();
for (var i = 0; i < listeners.length; i++) {
listeners[i].call(this, data);
}
return this;
},
/**
* Check if an event is registered to a type
* @returns {Boolean} Returns true if the object listens to an event of a particular type
*/
listens: function(type) {
return !!(this._events && this._events[type]);
}
};
module.exports = Evented;
},{"./util":96}],91:[function(require,module,exports){
'use strict';
module.exports = Glyphs;
function Glyphs(pbf, end) {
this.stacks = pbf.readFields(readFontstacks, [], end);
}
function readFontstacks(tag, stacks, pbf) {
if (tag === 1) {
var fontstack = pbf.readMessage(readFontstack, {glyphs: {}});
stacks.push(fontstack);
}
}
function readFontstack(tag, fontstack, pbf) {
if (tag === 1) fontstack.name = pbf.readString();
else if (tag === 2) fontstack.range = pbf.readString();
else if (tag === 3) {
var glyph = pbf.readMessage(readGlyph, {});
fontstack.glyphs[glyph.id] = glyph;
}
}
function readGlyph(tag, glyph, pbf) {
if (tag === 1) glyph.id = pbf.readVarint();
else if (tag === 2) glyph.bitmap = pbf.readBytes();
else if (tag === 3) glyph.width = pbf.readVarint();
else if (tag === 4) glyph.height = pbf.readVarint();
else if (tag === 5) glyph.left = pbf.readSVarint();
else if (tag === 6) glyph.top = pbf.readSVarint();
else if (tag === 7) glyph.advance = pbf.readVarint();
}
},{}],92:[function(require,module,exports){
'use strict';
module.exports = interpolate;
function interpolate(a, b, t) {
return (a * (1 - t)) + (b * t);
}
interpolate.number = interpolate;
interpolate.vec2 = function(from, to, t) {
return [
interpolate(from[0], to[0], t),
interpolate(from[1], to[1], t)
];
};
/*
* Interpolate between two colors given as 4-element arrays.
*
* @param {Color} from
* @param {Color} to
* @param {Number} t interpolation factor between 0 and 1
* @returns {Color} interpolated color
*/
interpolate.color = function(from, to, t) {
return [
interpolate(from[0], to[0], t),
interpolate(from[1], to[1], t),
interpolate(from[2], to[2], t),
interpolate(from[3], to[3], t)
];
};
interpolate.array = function(from, to, t) {
return from.map(function(d, i) {
return interpolate(d, to[i], t);
});
};
},{}],93:[function(require,module,exports){
'use strict';
var config = require('./config');
var browser = require('./browser');
function normalizeURL(url, pathPrefix, accessToken) {
accessToken = accessToken || config.ACCESS_TOKEN;
if (!accessToken && config.REQUIRE_ACCESS_TOKEN) {
throw new Error('An API access token is required to use Mapbox GL. ' +
'See https://www.mapbox.com/developers/api/#access-tokens');
}
var https = config.FORCE_HTTPS ||
(typeof document !== 'undefined' && document.location.protocol === 'https:');
url = url.replace(/^mapbox:\/\//, (https ? config.HTTPS_URL : config.HTTP_URL) + pathPrefix);
url += url.indexOf('?') !== -1 ? '&access_token=' : '?access_token=';
if (config.REQUIRE_ACCESS_TOKEN) {
if (accessToken[0] === 's') {
throw new Error('Use a public access token (pk.*) with Mapbox GL JS, not a secret access token (sk.*). ' +
'See https://www.mapbox.com/developers/api/#access-tokens');
}
url += accessToken;
}
return url;
}
module.exports.normalizeStyleURL = function(url, accessToken) {
var user = url.match(/^mapbox:\/\/([^.]+)/);
if (!user)
return url;
return normalizeURL(url, '/styles/v1/' + user[1] + '/', accessToken);
};
module.exports.normalizeSourceURL = function(url, accessToken) {
if (!url.match(/^mapbox:\/\//))
return url;
url = normalizeURL(url + '.json', '/v4/', accessToken);
// TileJSON requests need a secure flag appended to their URLs so
// that the server knows to send SSL-ified resource references.
if (url.indexOf('https') === 0)
url += '&secure';
return url;
};
module.exports.normalizeGlyphsURL = function(url, accessToken) {
if (!url.match(/^mapbox:\/\//))
return url;
return normalizeURL(url, '/v4/', accessToken);
};
module.exports.normalizeTileURL = function(url, sourceUrl) {
if (!sourceUrl || !sourceUrl.match(/^mapbox:\/\//))
return url;
return url.replace(/\.((?:png|jpg)\d*)(?=$|\?)/, browser.devicePixelRatio >= 2 ? '@2x.$1' : '.$1');
};
},{"./browser":85,"./config":89}],94:[function(require,module,exports){
'use strict';
/*
* A [most-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms)
* with hash lookup made possible by keeping a list of keys in parallel to
* an array of dictionary of values
*
* @param {number} max number of permitted values
* @param {Function} onRemove callback called with items when they expire
* @private
*/
module.exports = MRUCache;
function MRUCache(max, onRemove) {
this.max = max;
this.onRemove = onRemove;
this.reset();
}
/**
* Clear the cache
*
* @returns {MRUCache} this cache
*/
MRUCache.prototype.reset = function() {
for (var key in this.list) {
this.onRemove(this.list[key]);
}
this.list = {};
this.order = [];
return this;
};
/*
* Add a key, value combination to the cache, trimming its size if this pushes
* it over max length.
*
* @param {string} key lookup key for the item
* @param {*} data any value
*
* @returns {MRUCache} this cache
*/
MRUCache.prototype.add = function(key, data) {
this.list[key] = data;
this.order.push(key);
if (this.order.length > this.max) {
var removedData = this.get(this.order[0]);
if (removedData) this.onRemove(removedData);
}
return this;
};
/*
* Determine whether the value attached to `key` is present
*
* @param {string} key the key to be looked-up
* @returns {boolean} whether the cache has this value
*/
MRUCache.prototype.has = function(key) {
return key in this.list;
};
/*
* List all keys in the cache
*
* @returns {Array<string>} an array of keys in this cache.
*/
MRUCache.prototype.keys = function() {
return this.order;
};
/*
* Get the value attached to a specific key. If the key is not found,
* returns `null`
*
* @param {string} key the key to look up
* @returns {*} the data, or null if it isn't found
*/
MRUCache.prototype.get = function(key) {
if (!this.has(key)) { return null; }
var data = this.list[key];
delete this.list[key];
this.order.splice(this.order.indexOf(key), 1);
return data;
};
},{}],95:[function(require,module,exports){
'use strict';
module.exports = resolveTokens;
/**
* Replace tokens in a string template with values in an object
*
* @param {Object} properties a key/value relationship between tokens and replacements
* @param {string} text the template string
* @returns {string} the template with tokens replaced
* @private
*/
function resolveTokens(properties, text) {
return text.replace(/{([^{}()\[\]<>$=:;.,^]+)}/g, function(match, key) {
return key in properties ? properties[key] : '';
});
}
},{}],96:[function(require,module,exports){
'use strict';
var UnitBezier = require('unitbezier');
/**
* Given a value `t` that varies between 0 and 1, return
* an interpolation function that eases between 0 and 1 in a pleasing
* cubic in-out fashion.
*
* @param {number} t input
* @returns {number} input
*/
exports.easeCubicInOut = function (t) {
if (t <= 0) return 0;
if (t >= 1) return 1;
var t2 = t * t,
t3 = t2 * t;
return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75);
};
/**
* Given given (x, y), (x1, y1) control points for a bezier curve,
* return a function that interpolates along that curve.
*
* @param {number} p1x control point 1 x coordinate
* @param {number} p1y control point 1 y coordinate
* @param {number} p2x control point 2 x coordinate
* @param {number} p2y control point 2 y coordinate
* @returns {Function} interpolator: receives number value, returns
* number value.
*/
exports.bezier = function(p1x, p1y, p2x, p2y) {
var bezier = new UnitBezier(p1x, p1y, p2x, p2y);
return function(t) {
return bezier.solve(t);
};
};
/**
* A default bezier-curve powered easing function with
* control points (0.25, 0.1) and (0.25, 1)
*
* @param {number} t
* @returns {number} output
*/
exports.ease = exports.bezier(0.25, 0.1, 0.25, 1);
/**
* Given a four-element array of numbers that represents a color in
* RGBA, return a version for which the RGB components are multiplied
* by the A (alpha) component
*
* @param {Number<Array>} c color array
* @returns {Number<Array>} premultiplied color array
*/
exports.premultiply = function (c) {
c[0] *= c[3];
c[1] *= c[3];
c[2] *= c[3];
return c;
};
/**
* constrain n to the given range via min + max
*
* @param {Number} n value
* @param {Number} min the minimum value to be returned
* @param {Number} max the maximum value to be returned
* @returns {Number} the clamped value
*/
exports.clamp = function (n, min, max) {
return Math.min(max, Math.max(min, n));
};
/*
* constrain n to the given range via modular arithmetic
* @param {Number} n
* @param {Number} min
* @param {Number} max
* @returns {Number} constrained number
*/
exports.wrap = function (n, min, max) {
var d = max - min;
return n === max ? n : ((n - min) % d + d) % d + min;
};
/*
* return the first non-null and non-undefined argument to this function.
* @returns {*} argument
*/
exports.coalesce = function() {
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (arg !== null && arg !== undefined)
return arg;
}
};
/*
* Call an asynchronous function on an array of arguments,
* calling `callback` once all calls complete.
*
* @param {Array<*>} array input to each call of the async function.
* @param {Function} fn an async function with signature (data, callback)
* @param {Function} callback a callback run after all async work is done.
* called with no arguments
* @returns {undefined}
*/
exports.asyncEach = function (array, fn, callback) {
var remaining = array.length;
if (remaining === 0) return callback();
function check() { if (--remaining === 0) callback(); }
for (var i = 0; i < array.length; i++) fn(array[i], check);
};
/*
* Compute the difference between the keys in one object and the keys
* in another object.
*
* @param {Object} obj
* @param {Object} other
* @returns {Array<string>} keys difference
*/
exports.keysDifference = function (obj, other) {
var difference = [];
for (var i in obj) {
if (!(i in other)) {
difference.push(i);
}
}
return difference;
};
/**
* Given a destination object and optionally many source objects,
* copy all properties from the source objects into the destination.
* The last source object given overrides properties from previous
* source objects.
* @param {Object} dest destination object
* @param {...Object} sources sources from which properties are pulled
* @returns {Object} dest
*/
exports.extend = function (dest) {
for (var i = 1; i < arguments.length; i++) {
var src = arguments[i];
for (var k in src) {
dest[k] = src[k];
}
}
return dest;
};
/**
* Extend a destination object with all properties of the src object,
* using defineProperty instead of simple assignment.
* @param {Object} dest
* @param {Object} src
* @returns {Object} dest
*/
exports.extendAll = function (dest, src) {
for (var i in src) {
Object.defineProperty(dest, i, Object.getOwnPropertyDescriptor(src, i));
}
return dest;
};
/**
* Extend a parent's prototype with all properties in a properties
* object.
*
* @param {Object} parent
* @param {Object} props
* @returns {Object}
*/
exports.inherit = function (parent, props) {
var parentProto = typeof parent === 'function' ? parent.prototype : parent,
proto = Object.create(parentProto);
exports.extendAll(proto, props);
return proto;
};
/**
* Given an object and a number of properties as strings, return version
* of that object with only those properties.
*
* @param {Object} src the object
* @param {Array<string>} properties an array of property names chosen
* to appear on the resulting object.
* @returns {Object} object with limited properties.
* @example
* var foo = { name: 'Charlie', age: 10 };
* var justName = pick(foo, ['name']);
* // justName = { name: 'Charlie' }
*/
exports.pick = function (src, properties) {
var result = {};
for (var i = 0; i < properties.length; i++) {
var k = properties[i];
if (k in src) {
result[k] = src[k];
}
}
return result;
};
var id = 1;
/**
* Return a unique numeric id, starting at 1 and incrementing with
* each call.
*
* @returns {Number} unique numeric id.
*/
exports.uniqueId = function () {
return id++;
};
/**
* Create a version of `fn` that only fires once every `time` millseconds.
*
* @param {Function} fn the function to be throttled
* @param {Number} time millseconds required between function calls
* @param {*} context the value of `this` with which the function is called
* @returns {Function} debounced function
*/
exports.throttle = function (fn, time, context) {
var lock, args, wrapperFn, later;
later = function () {
// reset lock and call if queued
lock = false;
if (args) {
wrapperFn.apply(context, args);
args = false;
}
};
wrapperFn = function () {
if (lock) {
// called too soon, queue to call later
args = arguments;
} else {
// call and lock until later
fn.apply(context, arguments);
setTimeout(later, time);
lock = true;
}
};
return wrapperFn;
};
/**
* Create a version of `fn` that is only called `time` milliseconds
* after its last invocation
*
* @param {Function} fn the function to be debounced
* @param {Number} time millseconds after which the function will be invoked
* @returns {Function} debounced function
*/
exports.debounce = function(fn, time) {
var timer, args;
return function() {
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(null, args);
}, time);
};
};
/**
* Given an array of member function names as strings, replace all of them
* with bound versions that will always refer to `context` as `this`. This
* is useful for classes where otherwise event bindings would reassign
* `this` to the evented object or some other value: this lets you ensure
* the `this` value always.
*
* @param {Array<string>} fns list of member function names
* @param {*} context the context value
* @returns {undefined} changes functions in-place
* @example
* function MyClass() {
* bindAll(['ontimer'], this);
* this.name = 'Tom';
* }
* MyClass.prototype.ontimer = function() {
* alert(this.name);
* };
* var myClass = new MyClass();
* setTimeout(myClass.ontimer, 100);
*/
exports.bindAll = function(fns, context) {
fns.forEach(function(fn) {
context[fn] = context[fn].bind(context);
});
};
/**
* Set the 'options' property on `obj` with properties
* from the `options` argument. Properties in the `options`
* object will override existing properties.
*
* @param {Object} obj destination object
* @param {Object} options object of override options
* @returns {Object} derived options object.
*/
exports.setOptions = function(obj, options) {
if (!obj.hasOwnProperty('options')) {
obj.options = obj.options ? Object.create(obj.options) : {};
}
for (var i in options) {
obj.options[i] = options[i];
}
return obj.options;
};
},{"unitbezier":116}],97:[function(require,module,exports){
// (c) Dean McNamee <dean@gmail.com>, 2012.
//
// https://github.com/deanm/css-color-parser-js
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// http://www.w3.org/TR/css3-color/
var kCSSColorTable = {
"transparent": [0,0,0,0], "aliceblue": [240,248,255,1],
"antiquewhite": [250,235,215,1], "aqua": [0,255,255,1],
"aquamarine": [127,255,212,1], "azure": [240,255,255,1],
"beige": [245,245,220,1], "bisque": [255,228,196,1],
"black": [0,0,0,1], "blanchedalmond": [255,235,205,1],
"blue": [0,0,255,1], "blueviolet": [138,43,226,1],
"brown": [165,42,42,1], "burlywood": [222,184,135,1],
"cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1],
"chocolate": [210,105,30,1], "coral": [255,127,80,1],
"cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1],
"crimson": [220,20,60,1], "cyan": [0,255,255,1],
"darkblue": [0,0,139,1], "darkcyan": [0,139,139,1],
"darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1],
"darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1],
"darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1],
"darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1],
"darkorchid": [153,50,204,1], "darkred": [139,0,0,1],
"darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1],
"darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1],
"darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1],
"darkviolet": [148,0,211,1], "deeppink": [255,20,147,1],
"deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1],
"dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1],
"firebrick": [178,34,34,1], "floralwhite": [255,250,240,1],
"forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1],
"gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1],
"gold": [255,215,0,1], "goldenrod": [218,165,32,1],
"gray": [128,128,128,1], "green": [0,128,0,1],
"greenyellow": [173,255,47,1], "grey": [128,128,128,1],
"honeydew": [240,255,240,1], "hotpink": [255,105,180,1],
"indianred": [205,92,92,1], "indigo": [75,0,130,1],
"ivory": [255,255,240,1], "khaki": [240,230,140,1],
"lavender": [230,230,250,1], "lavenderblush": [255,240,245,1],
"lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1],
"lightblue": [173,216,230,1], "lightcoral": [240,128,128,1],
"lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1],
"lightgray": [211,211,211,1], "lightgreen": [144,238,144,1],
"lightgrey": [211,211,211,1], "lightpink": [255,182,193,1],
"lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1],
"lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1],
"lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1],
"lightyellow": [255,255,224,1], "lime": [0,255,0,1],
"limegreen": [50,205,50,1], "linen": [250,240,230,1],
"magenta": [255,0,255,1], "maroon": [128,0,0,1],
"mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1],
"mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1],
"mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1],
"mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1],
"mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1],
"mintcream": [245,255,250,1], "mistyrose": [255,228,225,1],
"moccasin": [255,228,181,1], "navajowhite": [255,222,173,1],
"navy": [0,0,128,1], "oldlace": [253,245,230,1],
"olive": [128,128,0,1], "olivedrab": [107,142,35,1],
"orange": [255,165,0,1], "orangered": [255,69,0,1],
"orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1],
"palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1],
"palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1],
"peachpuff": [255,218,185,1], "peru": [205,133,63,1],
"pink": [255,192,203,1], "plum": [221,160,221,1],
"powderblue": [176,224,230,1], "purple": [128,0,128,1],
"red": [255,0,0,1], "rosybrown": [188,143,143,1],
"royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1],
"salmon": [250,128,114,1], "sandybrown": [244,164,96,1],
"seagreen": [46,139,87,1], "seashell": [255,245,238,1],
"sienna": [160,82,45,1], "silver": [192,192,192,1],
"skyblue": [135,206,235,1], "slateblue": [106,90,205,1],
"slategray": [112,128,144,1], "slategrey": [112,128,144,1],
"snow": [255,250,250,1], "springgreen": [0,255,127,1],
"steelblue": [70,130,180,1], "tan": [210,180,140,1],
"teal": [0,128,128,1], "thistle": [216,191,216,1],
"tomato": [255,99,71,1], "turquoise": [64,224,208,1],
"violet": [238,130,238,1], "wheat": [245,222,179,1],
"white": [255,255,255,1], "whitesmoke": [245,245,245,1],
"yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]}
function clamp_css_byte(i) { // Clamp to integer 0 .. 255.
i = Math.round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.
return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) { // int or percentage.
if (str[str.length - 1] === '%')
return clamp_css_byte(parseFloat(str) / 100 * 255);
return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) { // float or percentage.
if (str[str.length - 1] === '%')
return clamp_css_float(parseFloat(str) / 100);
return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
if (h < 0) h += 1;
else if (h > 1) h -= 1;
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
return m1;
}
function parseCSSColor(css_str) {
// Remove all whitespace, not compliant, but should just be more accepting.
var str = css_str.replace(/ /g, '').toLowerCase();
// Color keywords (and transparent) lookup.
if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup.
// #abc and #abc123 syntax.
if (str[0] === '#') {
if (str.length === 4) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN.
return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
(iv & 0xf0) | ((iv & 0xf0) >> 4),
(iv & 0xf) | ((iv & 0xf) << 4),
1];
} else if (str.length === 7) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN.
return [(iv & 0xff0000) >> 16,
(iv & 0xff00) >> 8,
iv & 0xff,
1];
}
return null;
}
var op = str.indexOf('('), ep = str.indexOf(')');
if (op !== -1 && ep + 1 === str.length) {
var fname = str.substr(0, op);
var params = str.substr(op+1, ep-(op+1)).split(',');
var alpha = 1; // To allow case fallthrough.
switch (fname) {
case 'rgba':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'rgb':
if (params.length !== 3) return null;
return [parse_css_int(params[0]),
parse_css_int(params[1]),
parse_css_int(params[2]),
alpha];
case 'hsla':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'hsl':
if (params.length !== 3) return null;
var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1
// NOTE(deanm): According to the CSS spec s/l should only be
// percentages, but we don't bother and let float or percentage.
var s = parse_css_float(params[1]);
var l = parse_css_float(params[2]);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),
alpha];
default:
return null;
}
}
return null;
}
try { exports.parseCSSColor = parseCSSColor } catch(e) { }
},{}],98:[function(require,module,exports){
'use strict';
var VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
function infix(operator) {
return function(_, key, value) {
if (key === '$type') {
return 't' + operator + VectorTileFeatureTypes.indexOf(value);
} else {
return 'p[' + JSON.stringify(key) + ']' + operator + JSON.stringify(value);
}
};
}
function strictInfix(operator) {
var nonstrictInfix = infix(operator);
return function(_, key, value) {
if (key === '$type') {
return nonstrictInfix(_, key, value);
} else {
return 'typeof(p[' + JSON.stringify(key) + ']) === typeof(' + JSON.stringify(value) + ') && ' +
nonstrictInfix(_, key, value);
}
};
}
var operators = {
'==': infix('==='),
'!=': infix('!=='),
'>': strictInfix('>'),
'<': strictInfix('<'),
'<=': strictInfix('<='),
'>=': strictInfix('>='),
'in': function(_, key) {
return Array.prototype.slice.call(arguments, 2).map(function(value) {
return '(' + operators['=='](_, key, value) + ')';
}).join('||') || 'false';
},
'!in': function() {
return '!(' + operators.in.apply(this, arguments) + ')';
},
'any': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('||') || 'false';
},
'all': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('&&') || 'true';
},
'none': function() {
return '!(' + operators.any.apply(this, arguments) + ')';
}
};
function compile(filter) {
return operators[filter[0]].apply(filter, filter);
}
function truth() {
return true;
}
/**
* Given a filter expressed as nested arrays, return a new function
* that evaluates whether a given feature (with a .properties or .tags property)
* passes its test.
*
* @param {Array} filter mapbox gl filter
* @returns {Function} filter-evaluating function
*/
module.exports = function (filter) {
if (!filter) return truth;
var filterStr = 'var p = f.properties || f.tags || {}, t = f.type; return ' + compile(filter) + ';';
// jshint evil: true
return new Function('f', filterStr);
};
},{}],99:[function(require,module,exports){
'use strict';
module.exports = clip;
/* clip features between two axis-parallel lines:
* | |
* ___|___ | /
* / | \____|____/
* | |
*/
function clip(features, scale, k1, k2, axis, intersect) {
k1 /= scale;
k2 /= scale;
var clipped = [];
for (var i = 0; i < features.length; i++) {
var feature = features[i],
geometry = feature.geometry,
type = feature.type,
min, max;
if (feature.min) {
min = feature.min[axis];
max = feature.max[axis];
if (min >= k1 && max <= k2) { // trivial accept
clipped.push(feature);
continue;
} else if (min > k2 || max < k1) continue; // trivial reject
}
var slices = type === 1 ?
clipPoints(geometry, k1, k2, axis) :
clipGeometry(geometry, k1, k2, axis, intersect, type === 3);
if (slices.length) {
// if a feature got clipped, it will likely get clipped on the next zoom level as well,
// so there's no need to recalculate bboxes
clipped.push({
geometry: slices,
type: type,
tags: features[i].tags || null
});
}
}
return clipped.length ? clipped : null;
}
function clipPoints(geometry, k1, k2, axis) {
var slice = [];
for (var i = 0; i < geometry.length; i++) {
var a = geometry[i],
ak = a[axis];
if (ak >= k1 && ak <= k2) slice.push(a);
}
return slice;
}
function clipGeometry(geometry, k1, k2, axis, intersect, closed) {
var slices = [];
for (var i = 0; i < geometry.length; i++) {
var ak = 0,
bk = 0,
b = null,
points = geometry[i],
area = points.area,
dist = points.dist,
len = points.length,
a, j;
var slice = [];
for (j = 0; j < len - 1; j++) {
a = b || points[j];
b = points[j + 1];
ak = bk || a[axis];
bk = b[axis];
if (ak < k1) {
if ((bk > k2)) { // ---|-----|-->
slice.push(intersect(a, b, k1), intersect(a, b, k2));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk >= k1) slice.push(intersect(a, b, k1)); // ---|--> |
} else if (ak > k2) {
if ((bk < k1)) { // <--|-----|---
slice.push(intersect(a, b, k2), intersect(a, b, k1));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk <= k2) slice.push(intersect(a, b, k2)); // | <--|---
} else {
slice.push(a);
if (bk < k1) { // <--|--- |
slice.push(intersect(a, b, k1));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk > k2) { // | ---|-->
slice.push(intersect(a, b, k2));
if (!closed) slice = newSlice(slices, slice, area, dist);
}
// | --> |
}
}
// add the last point
a = points[len - 1];
ak = a[axis];
if (ak >= k1 && ak <= k2) slice.push(a);
// close the polygon if its endpoints are not the same after clipping
if (closed && slice[0] !== slice[slice.length - 1]) slice.push(slice[0]);
// add the final slice
newSlice(slices, slice, area, dist);
}
return slices;
}
function newSlice(slices, slice, area, dist) {
if (slice.length) {
// we don't recalculate the area/length of the unclipped geometry because the case where it goes
// below the visibility threshold as a result of clipping is rare, so we avoid doing unnecessary work
slice.area = area;
slice.dist = dist;
slices.push(slice);
}
return [];
}
},{}],100:[function(require,module,exports){
'use strict';
module.exports = convert;
var simplify = require('./simplify');
// converts GeoJSON feature into an intermediate projected JSON vector format with simplification data
function convert(data, tolerance) {
var features = [];
if (data.type === 'FeatureCollection') {
for (var i = 0; i < data.features.length; i++) {
convertFeature(features, data.features[i], tolerance);
}
} else if (data.type === 'Feature') {
convertFeature(features, data, tolerance);
} else {
// single geometry or a geometry collection
convertFeature(features, {geometry: data}, tolerance);
}
return features;
}
function convertFeature(features, feature, tolerance) {
var geom = feature.geometry,
type = geom.type,
coords = geom.coordinates,
tags = feature.properties,
i, j, rings;
if (type === 'Point') {
features.push(create(tags, 1, [projectPoint(coords)]));
} else if (type === 'MultiPoint') {
features.push(create(tags, 1, project(coords)));
} else if (type === 'LineString') {
features.push(create(tags, 2, [project(coords, tolerance)]));
} else if (type === 'MultiLineString' || type === 'Polygon') {
rings = [];
for (i = 0; i < coords.length; i++) {
rings.push(project(coords[i], tolerance));
}
features.push(create(tags, type === 'Polygon' ? 3 : 2, rings));
} else if (type === 'MultiPolygon') {
rings = [];
for (i = 0; i < coords.length; i++) {
for (j = 0; j < coords[i].length; j++) {
rings.push(project(coords[i][j], tolerance));
}
}
features.push(create(tags, 3, rings));
} else if (type === 'GeometryCollection') {
for (i = 0; i < geom.geometries.length; i++) {
convertFeature(features, {
geometry: geom.geometries[i],
properties: tags
}, tolerance);
}
} else {
console.warn('Unsupported GeoJSON type: ' + geom.type);
}
}
function create(tags, type, geometry) {
var feature = {
geometry: geometry,
type: type,
tags: tags || null,
min: [1, 1], // initial bbox values;
max: [0, 0] // note that all coords are in [0..1] range
};
calcBBox(feature);
return feature;
}
function project(lonlats, tolerance) {
var projected = [];
for (var i = 0; i < lonlats.length; i++) {
projected.push(projectPoint(lonlats[i]));
}
if (tolerance) {
simplify(projected, tolerance);
calcSize(projected);
}
return projected;
}
function projectPoint(p) {
var sin = Math.sin(p[1] * Math.PI / 180),
x = (p[0] / 360 + 0.5),
y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
return [x, y, 0];
}
// calculate area and length of the poly
function calcSize(points) {
var area = 0,
dist = 0;
for (var i = 0, a, b; i < points.length - 1; i++) {
a = b || points[i];
b = points[i + 1];
area += a[0] * b[1] - b[0] * a[1];
// use Manhattan distance instead of Euclidian one to avoid expensive square root computation
dist += Math.abs(b[0] - a[0]) + Math.abs(b[1] - a[1]);
}
points.area = Math.abs(area / 2);
points.dist = dist;
}
// calculate the feature bounding box for faster clipping later
function calcBBox(feature) {
var geometry = feature.geometry,
min = feature.min,
max = feature.max;
if (feature.type === 1) calcRingBBox(min, max, geometry);
else for (var i = 0; i < geometry.length; i++) calcRingBBox(min, max, geometry[i]);
return feature;
}
function calcRingBBox(min, max, points) {
for (var i = 0, p; i < points.length; i++) {
p = points[i];
min[0] = Math.min(p[0], min[0]);
max[0] = Math.max(p[0], max[0]);
min[1] = Math.min(p[1], min[1]);
max[1] = Math.max(p[1], max[1]);
}
}
},{"./simplify":102}],101:[function(require,module,exports){
'use strict';
module.exports = geojsonvt;
var convert = require('./convert'), // GeoJSON conversion and preprocessing
clip = require('./clip'), // stripe clipping algorithm
createTile = require('./tile'); // final simplified tile generation
function geojsonvt(data, options) {
return new GeoJSONVT(data, options);
}
function GeoJSONVT(data, options) {
options = this.options = extend(Object.create(this.options), options);
var debug = options.debug;
if (debug) console.time('preprocess data');
var z2 = 1 << options.baseZoom, // 2^z
features = convert(data, options.tolerance / (z2 * options.extent));
this.tiles = {};
if (debug) {
console.timeEnd('preprocess data');
console.time('generate tiles up to z' + options.maxZoom);
this.stats = {};
this.total = 0;
}
// start slicing from the top tile down
this.splitTile(features, 0, 0, 0);
if (debug) {
console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints);
console.timeEnd('generate tiles up to z' + options.maxZoom);
console.log('tiles generated:', this.total, JSON.stringify(this.stats));
}
}
GeoJSONVT.prototype.options = {
baseZoom: 14, // max zoom to preserve detail on
maxZoom: 4, // zoom to slice down to on first pass
maxPoints: 100, // stop slicing a tile below this number of points
tolerance: 3, // simplification tolerance (higher means simpler)
extent: 4096, // tile extent
buffer: 64, // tile buffer on each side
debug: 0 // logging level (0, 1 or 2)
};
GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) {
var stack = [features, z, x, y],
options = this.options,
debug = options.debug,
extent = options.extent,
buffer = options.buffer;
// avoid recursion by using a processing queue
while (stack.length) {
features = stack.shift();
z = stack.shift();
x = stack.shift();
y = stack.shift();
var z2 = 1 << z,
id = toID(z, x, y),
tile = this.tiles[id],
tileTolerance = z === options.baseZoom ? 0 : options.tolerance / (z2 * extent);
if (!tile) {
if (debug > 1) console.time('creation');
tile = this.tiles[id] = createTile(features, z2, x, y, tileTolerance, extent, z === options.baseZoom);
if (debug) {
if (debug > 1) {
console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)',
z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified);
console.timeEnd('creation');
}
var key = 'z' + z + ':';
this.stats[key] = (this.stats[key] || 0) + 1;
this.total++;
}
}
if (!cz && (z === options.maxZoom || tile.numPoints <= options.maxPoints ||
isClippedSquare(tile.features, extent, buffer)) || z === options.baseZoom || z === cz) {
tile.source = features;
continue; // stop tiling
}
if (cz) tile.source = features;
else tile.source = null;
if (debug > 1) console.time('clipping');
// values we'll use for clipping
var k1 = 0.5 * buffer / extent,
k2 = 0.5 - k1,
k3 = 0.5 + k1,
k4 = 1 + k1,
tl, bl, tr, br, left, right,
m, goLeft, goTop;
if (cz) { // if we have a specific tile to drill down to, calculate where to go
m = 1 << (cz - z);
goLeft = cx / m - x < 0.5;
goTop = cy / m - y < 0.5;
}
tl = bl = tr = br = left = right = null;
if (!cz || goLeft) left = clip(features, z2, x - k1, x + k3, 0, intersectX);
if (!cz || !goLeft) right = clip(features, z2, x + k2, x + k4, 0, intersectX);
if (left) {
if (!cz || goTop) tl = clip(left, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) bl = clip(left, z2, y + k2, y + k4, 1, intersectY);
}
if (right) {
if (!cz || goTop) tr = clip(right, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) br = clip(right, z2, y + k2, y + k4, 1, intersectY);
}
if (debug > 1) console.timeEnd('clipping');
if (tl) stack.push(tl, z + 1, x * 2, y * 2);
if (bl) stack.push(bl, z + 1, x * 2, y * 2 + 1);
if (tr) stack.push(tr, z + 1, x * 2 + 1, y * 2);
if (br) stack.push(br, z + 1, x * 2 + 1, y * 2 + 1);
}
};
GeoJSONVT.prototype.getTile = function (z, x, y) {
var id = toID(z, x, y);
if (this.tiles[id]) return this.tiles[id];
var options = this.options,
debug = options.debug;
if (debug > 1) console.log('drilling down to z%d-%d-%d', z, x, y);
var z0 = z,
x0 = x,
y0 = y,
parent;
while (!parent && z0 > 0) {
z0--;
x0 = Math.floor(x0 / 2);
y0 = Math.floor(y0 / 2);
parent = this.tiles[toID(z0, x0, y0)];
}
if (debug > 1) console.log('found parent tile z%d-%d-%d', z0, x0, y0);
// if we found a parent tile containing the original geometry, we can drill down from it
if (parent.source) {
if (isClippedSquare(parent.features, options.extent, options.buffer)) return parent;
if (debug) console.time('drilling down');
this.splitTile(parent.source, z0, x0, y0, z, x, y);
if (debug) console.timeEnd('drilling down');
}
return this.tiles[id];
};
// checks whether a tile is a whole-area fill after clipping; if it is, there's no sense slicing it further
function isClippedSquare(features, extent, buffer) {
if (features.length !== 1) return false;
var feature = features[0];
if (feature.type !== 3 || feature.geometry.length > 1) return false;
for (var i = 0; i < feature.geometry[0].length; i++) {
var p = feature.geometry[0][i];
if ((p[0] !== -buffer && p[0] !== extent + buffer) ||
(p[1] !== -buffer && p[1] !== extent + buffer)) return false;
}
return true;
}
function toID(z, x, y) {
return (((1 << z) * y + x) * 32) + z;
}
function intersectX(a, b, x) {
return [x, (x - a[0]) * (b[1] - a[1]) / (b[0] - a[0]) + a[1], 1];
}
function intersectY(a, b, y) {
return [(y - a[1]) * (b[0] - a[0]) / (b[1] - a[1]) + a[0], y, 1];
}
function extend(dest, src) {
for (var i in src) dest[i] = src[i];
return dest;
}
},{"./clip":99,"./convert":100,"./tile":103}],102:[function(require,module,exports){
'use strict';
module.exports = simplify;
// calculate simplification data using optimized Douglas-Peucker algorithm
function simplify(points, tolerance) {
var sqTolerance = tolerance * tolerance,
len = points.length,
first = 0,
last = len - 1,
stack = [],
i, maxSqDist, sqDist, index;
// always retain the endpoints (1 is the max value)
points[first][2] = 1;
points[last][2] = 1;
// avoid recursion by using a stack
while (last) {
maxSqDist = 0;
for (i = first + 1; i < last; i++) {
sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate
stack.push(first, index, index, last);
}
last = stack.pop();
first = stack.pop();
}
}
// square distance from a point to a segment
function getSqSegDist(p, a, b) {
var x = a[0], y = a[1],
bx = b[0], by = b[1],
px = p[0], py = p[1],
dx = bx - x,
dy = by - y;
if (dx !== 0 || dy !== 0) {
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = bx;
y = by;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = px - x;
dy = py - y;
return dx * dx + dy * dy;
}
},{}],103:[function(require,module,exports){
'use strict';
module.exports = createTile;
function createTile(features, z2, tx, ty, tolerance, extent, noSimplify) {
var tile = {
features: [],
numPoints: 0,
numSimplified: 0,
numFeatures: 0,
source: null
};
for (var i = 0; i < features.length; i++) {
tile.numFeatures++;
addFeature(tile, features[i], z2, tx, ty, tolerance, extent, noSimplify);
}
return tile;
}
function addFeature(tile, feature, z2, tx, ty, tolerance, extent, noSimplify) {
var geom = feature.geometry,
type = feature.type,
transformed = [],
sqTolerance = tolerance * tolerance,
i, j, ring, p;
if (type === 1) {
for (i = 0; i < geom.length; i++) {
transformed.push(transformPoint(geom[i], z2, tx, ty, extent));
tile.numPoints++;
tile.numSimplified++;
}
} else {
// simplify and transform projected coordinates for tile geometry
for (i = 0; i < geom.length; i++) {
ring = geom[i];
// filter out tiny polylines & polygons
if (!noSimplify && ((type === 2 && ring.dist < tolerance) ||
(type === 3 && ring.area < sqTolerance))) {
tile.numPoints += ring.length;
continue;
}
var transformedRing = [];
for (j = 0; j < ring.length; j++) {
p = ring[j];
// keep points with importance > tolerance
if (noSimplify || p[2] > sqTolerance) {
transformedRing.push(transformPoint(p, z2, tx, ty, extent));
tile.numSimplified++;
}
tile.numPoints++;
}
transformed.push(transformedRing);
}
}
if (transformed.length) {
tile.features.push({
geometry: transformed,
type: type,
tags: feature.tags || null
});
}
}
function transformPoint(p, z2, tx, ty, extent) {
var x = Math.round(extent * (p[0] * z2 - tx)),
y = Math.round(extent * (p[1] * z2 - ty));
return [x, y];
}
},{}],104:[function(require,module,exports){
/**
* @fileoverview gl-matrix - High performance matrix and vector operations
* @author Brandon Jones
* @author Colin MacKenzie IV
* @version 2.2.1
*/
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
(function(_global) {
"use strict";
var shim = {};
if (typeof(exports) === 'undefined') {
if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
shim.exports = {};
define(function() {
return shim.exports;
});
} else {
// gl-matrix lives in a browser, define its namespaces in global
shim.exports = typeof(window) !== 'undefined' ? window : _global;
}
}
else {
// gl-matrix lives in commonjs, define its namespaces in exports
shim.exports = exports;
}
(function(exports) {
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
if(!GLMAT_EPSILON) {
var GLMAT_EPSILON = 0.000001;
}
if(!GLMAT_ARRAY_TYPE) {
var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
}
if(!GLMAT_RANDOM) {
var GLMAT_RANDOM = Math.random;
}
/**
* @class Common utilities
* @name glMatrix
*/
var glMatrix = {};
/**
* Sets the type of array used when creating new vectors and matricies
*
* @param {Type} type Array type, such as Float32Array or Array
*/
glMatrix.setMatrixArrayType = function(type) {
GLMAT_ARRAY_TYPE = type;
}
if(typeof(exports) !== 'undefined') {
exports.glMatrix = glMatrix;
}
var degree = Math.PI / 180;
/**
* Convert Degree To Radian
*
* @param {Number} Angle in Degrees
*/
glMatrix.toRadian = function(a){
return a * degree;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2 Dimensional Vector
* @name vec2
*/
var vec2 = {};
/**
* Creates a new, empty vec2
*
* @returns {vec2} a new 2D vector
*/
vec2.create = function() {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = 0;
out[1] = 0;
return out;
};
/**
* Creates a new vec2 initialized with values from an existing vector
*
* @param {vec2} a vector to clone
* @returns {vec2} a new 2D vector
*/
vec2.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = a[0];
out[1] = a[1];
return out;
};
/**
* Creates a new vec2 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} a new 2D vector
*/
vec2.fromValues = function(x, y) {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = x;
out[1] = y;
return out;
};
/**
* Copy the values from one vec2 to another
*
* @param {vec2} out the receiving vector
* @param {vec2} a the source vector
* @returns {vec2} out
*/
vec2.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
return out;
};
/**
* Set the components of a vec2 to the given values
*
* @param {vec2} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} out
*/
vec2.set = function(out, x, y) {
out[0] = x;
out[1] = y;
return out;
};
/**
* Adds two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
return out;
};
/**
* Alias for {@link vec2.subtract}
* @function
*/
vec2.sub = vec2.subtract;
/**
* Multiplies two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
return out;
};
/**
* Alias for {@link vec2.multiply}
* @function
*/
vec2.mul = vec2.multiply;
/**
* Divides two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
return out;
};
/**
* Alias for {@link vec2.divide}
* @function
*/
vec2.div = vec2.divide;
/**
* Returns the minimum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
return out;
};
/**
* Returns the maximum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
return out;
};
/**
* Scales a vec2 by a scalar number
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec2} out
*/
vec2.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
return out;
};
/**
* Adds two vec2's after scaling the second operand by a scalar value
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec2} out
*/
vec2.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} distance between a and b
*/
vec2.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return Math.sqrt(x*x + y*y);
};
/**
* Alias for {@link vec2.distance}
* @function
*/
vec2.dist = vec2.distance;
/**
* Calculates the squared euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} squared distance between a and b
*/
vec2.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return x*x + y*y;
};
/**
* Alias for {@link vec2.squaredDistance}
* @function
*/
vec2.sqrDist = vec2.squaredDistance;
/**
* Calculates the length of a vec2
*
* @param {vec2} a vector to calculate length of
* @returns {Number} length of a
*/
vec2.length = function (a) {
var x = a[0],
y = a[1];
return Math.sqrt(x*x + y*y);
};
/**
* Alias for {@link vec2.length}
* @function
*/
vec2.len = vec2.length;
/**
* Calculates the squared length of a vec2
*
* @param {vec2} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec2.squaredLength = function (a) {
var x = a[0],
y = a[1];
return x*x + y*y;
};
/**
* Alias for {@link vec2.squaredLength}
* @function
*/
vec2.sqrLen = vec2.squaredLength;
/**
* Negates the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to negate
* @returns {vec2} out
*/
vec2.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
return out;
};
/**
* Normalize a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to normalize
* @returns {vec2} out
*/
vec2.normalize = function(out, a) {
var x = a[0],
y = a[1];
var len = x*x + y*y;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
}
return out;
};
/**
* Calculates the dot product of two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} dot product of a and b
*/
vec2.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1];
};
/**
* Computes the cross product of two vec2's
* Note that the cross product must by definition produce a 3D vector
*
* @param {vec3} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec3} out
*/
vec2.cross = function(out, a, b) {
var z = a[0] * b[1] - a[1] * b[0];
out[0] = out[1] = 0;
out[2] = z;
return out;
};
/**
* Performs a linear interpolation between two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec2} out
*/
vec2.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec2} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec2} out
*/
vec2.random = function (out, scale) {
scale = scale || 1.0;
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
out[0] = Math.cos(r) * scale;
out[1] = Math.sin(r) * scale;
return out;
};
/**
* Transforms the vec2 with a mat2
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat2 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y;
out[1] = m[1] * x + m[3] * y;
return out;
};
/**
* Transforms the vec2 with a mat2d
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2d} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat2d = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y + m[4];
out[1] = m[1] * x + m[3] * y + m[5];
return out;
};
/**
* Transforms the vec2 with a mat3
* 3rd vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat3} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat3 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[3] * y + m[6];
out[1] = m[1] * x + m[4] * y + m[7];
return out;
};
/**
* Transforms the vec2 with a mat4
* 3rd vector component is implicitly '0'
* 4th vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat4 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[4] * y + m[12];
out[1] = m[1] * x + m[5] * y + m[13];
return out;
};
/**
* Perform some operation over an array of vec2s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec2.forEach = (function() {
var vec = vec2.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 2;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec2} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec2.str = function (a) {
return 'vec2(' + a[0] + ', ' + a[1] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec2 = vec2;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 3 Dimensional Vector
* @name vec3
*/
var vec3 = {};
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
vec3.create = function() {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = 0;
out[1] = 0;
out[2] = 0;
return out;
};
/**
* Creates a new vec3 initialized with values from an existing vector
*
* @param {vec3} a vector to clone
* @returns {vec3} a new 3D vector
*/
vec3.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
};
/**
* Creates a new vec3 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} a new 3D vector
*/
vec3.fromValues = function(x, y, z) {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = x;
out[1] = y;
out[2] = z;
return out;
};
/**
* Copy the values from one vec3 to another
*
* @param {vec3} out the receiving vector
* @param {vec3} a the source vector
* @returns {vec3} out
*/
vec3.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
};
/**
* Set the components of a vec3 to the given values
*
* @param {vec3} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} out
*/
vec3.set = function(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
return out;
};
/**
* Adds two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
return out;
};
/**
* Alias for {@link vec3.subtract}
* @function
*/
vec3.sub = vec3.subtract;
/**
* Multiplies two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
return out;
};
/**
* Alias for {@link vec3.multiply}
* @function
*/
vec3.mul = vec3.multiply;
/**
* Divides two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
return out;
};
/**
* Alias for {@link vec3.divide}
* @function
*/
vec3.div = vec3.divide;
/**
* Returns the minimum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
return out;
};
/**
* Returns the maximum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
return out;
};
/**
* Scales a vec3 by a scalar number
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec3} out
*/
vec3.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
return out;
};
/**
* Adds two vec3's after scaling the second operand by a scalar value
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec3} out
*/
vec3.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} distance between a and b
*/
vec3.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2];
return Math.sqrt(x*x + y*y + z*z);
};
/**
* Alias for {@link vec3.distance}
* @function
*/
vec3.dist = vec3.distance;
/**
* Calculates the squared euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} squared distance between a and b
*/
vec3.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2];
return x*x + y*y + z*z;
};
/**
* Alias for {@link vec3.squaredDistance}
* @function
*/
vec3.sqrDist = vec3.squaredDistance;
/**
* Calculates the length of a vec3
*
* @param {vec3} a vector to calculate length of
* @returns {Number} length of a
*/
vec3.length = function (a) {
var x = a[0],
y = a[1],
z = a[2];
return Math.sqrt(x*x + y*y + z*z);
};
/**
* Alias for {@link vec3.length}
* @function
*/
vec3.len = vec3.length;
/**
* Calculates the squared length of a vec3
*
* @param {vec3} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec3.squaredLength = function (a) {
var x = a[0],
y = a[1],
z = a[2];
return x*x + y*y + z*z;
};
/**
* Alias for {@link vec3.squaredLength}
* @function
*/
vec3.sqrLen = vec3.squaredLength;
/**
* Negates the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to negate
* @returns {vec3} out
*/
vec3.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
return out;
};
/**
* Normalize a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to normalize
* @returns {vec3} out
*/
vec3.normalize = function(out, a) {
var x = a[0],
y = a[1],
z = a[2];
var len = x*x + y*y + z*z;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
out[2] = a[2] * len;
}
return out;
};
/**
* Calculates the dot product of two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} dot product of a and b
*/
vec3.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
};
/**
* Computes the cross product of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.cross = function(out, a, b) {
var ax = a[0], ay = a[1], az = a[2],
bx = b[0], by = b[1], bz = b[2];
out[0] = ay * bz - az * by;
out[1] = az * bx - ax * bz;
out[2] = ax * by - ay * bx;
return out;
};
/**
* Performs a linear interpolation between two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec3} out
*/
vec3.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1],
az = a[2];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec3} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec3} out
*/
vec3.random = function (out, scale) {
scale = scale || 1.0;
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
var z = (GLMAT_RANDOM() * 2.0) - 1.0;
var zScale = Math.sqrt(1.0-z*z) * scale;
out[0] = Math.cos(r) * zScale;
out[1] = Math.sin(r) * zScale;
out[2] = z * scale;
return out;
};
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec3} out
*/
vec3.transformMat4 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2];
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
return out;
};
/**
* Transforms the vec3 with a mat3.
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m the 3x3 matrix to transform with
* @returns {vec3} out
*/
vec3.transformMat3 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2];
out[0] = x * m[0] + y * m[3] + z * m[6];
out[1] = x * m[1] + y * m[4] + z * m[7];
out[2] = x * m[2] + y * m[5] + z * m[8];
return out;
};
/**
* Transforms the vec3 with a quat
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec3} out
*/
vec3.transformQuat = function(out, a, q) {
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
var x = a[0], y = a[1], z = a[2],
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
// calculate quat * vec
ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return out;
};
/*
* Rotate a 3D vector around the x-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateX = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0];
r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/*
* Rotate a 3D vector around the y-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateY = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
r[1] = p[1];
r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/*
* Rotate a 3D vector around the z-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateZ = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
r[2] = p[2];
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/**
* Perform some operation over an array of vec3s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec3.forEach = (function() {
var vec = vec3.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 3;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec3} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec3.str = function (a) {
return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec3 = vec3;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 4 Dimensional Vector
* @name vec4
*/
var vec4 = {};
/**
* Creates a new, empty vec4
*
* @returns {vec4} a new 4D vector
*/
vec4.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 0;
return out;
};
/**
* Creates a new vec4 initialized with values from an existing vector
*
* @param {vec4} a vector to clone
* @returns {vec4} a new 4D vector
*/
vec4.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Creates a new vec4 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} a new 4D vector
*/
vec4.fromValues = function(x, y, z, w) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
};
/**
* Copy the values from one vec4 to another
*
* @param {vec4} out the receiving vector
* @param {vec4} a the source vector
* @returns {vec4} out
*/
vec4.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Set the components of a vec4 to the given values
*
* @param {vec4} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} out
*/
vec4.set = function(out, x, y, z, w) {
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
};
/**
* Adds two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
return out;
};
/**
* Alias for {@link vec4.subtract}
* @function
*/
vec4.sub = vec4.subtract;
/**
* Multiplies two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
out[3] = a[3] * b[3];
return out;
};
/**
* Alias for {@link vec4.multiply}
* @function
*/
vec4.mul = vec4.multiply;
/**
* Divides two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
out[3] = a[3] / b[3];
return out;
};
/**
* Alias for {@link vec4.divide}
* @function
*/
vec4.div = vec4.divide;
/**
* Returns the minimum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
out[3] = Math.min(a[3], b[3]);
return out;
};
/**
* Returns the maximum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
out[3] = Math.max(a[3], b[3]);
return out;
};
/**
* Scales a vec4 by a scalar number
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec4} out
*/
vec4.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
return out;
};
/**
* Adds two vec4's after scaling the second operand by a scalar value
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec4} out
*/
vec4.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} distance between a and b
*/
vec4.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2],
w = b[3] - a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
};
/**
* Alias for {@link vec4.distance}
* @function
*/
vec4.dist = vec4.distance;
/**
* Calculates the squared euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} squared distance between a and b
*/
vec4.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2],
w = b[3] - a[3];
return x*x + y*y + z*z + w*w;
};
/**
* Alias for {@link vec4.squaredDistance}
* @function
*/
vec4.sqrDist = vec4.squaredDistance;
/**
* Calculates the length of a vec4
*
* @param {vec4} a vector to calculate length of
* @returns {Number} length of a
*/
vec4.length = function (a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
};
/**
* Alias for {@link vec4.length}
* @function
*/
vec4.len = vec4.length;
/**
* Calculates the squared length of a vec4
*
* @param {vec4} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec4.squaredLength = function (a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
return x*x + y*y + z*z + w*w;
};
/**
* Alias for {@link vec4.squaredLength}
* @function
*/
vec4.sqrLen = vec4.squaredLength;
/**
* Negates the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to negate
* @returns {vec4} out
*/
vec4.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = -a[3];
return out;
};
/**
* Normalize a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to normalize
* @returns {vec4} out
*/
vec4.normalize = function(out, a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
var len = x*x + y*y + z*z + w*w;
if (len > 0) {
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
out[2] = a[2] * len;
out[3] = a[3] * len;
}
return out;
};
/**
* Calculates the dot product of two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} dot product of a and b
*/
vec4.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
};
/**
* Performs a linear interpolation between two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec4} out
*/
vec4.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1],
az = a[2],
aw = a[3];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
out[3] = aw + t * (b[3] - aw);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec4} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec4} out
*/
vec4.random = function (out, scale) {
scale = scale || 1.0;
//TODO: This is a pretty awful way of doing this. Find something better.
out[0] = GLMAT_RANDOM();
out[1] = GLMAT_RANDOM();
out[2] = GLMAT_RANDOM();
out[3] = GLMAT_RANDOM();
vec4.normalize(out, out);
vec4.scale(out, out, scale);
return out;
};
/**
* Transforms the vec4 with a mat4.
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec4} out
*/
vec4.transformMat4 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2], w = a[3];
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
return out;
};
/**
* Transforms the vec4 with a quat
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec4} out
*/
vec4.transformQuat = function(out, a, q) {
var x = a[0], y = a[1], z = a[2],
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
// calculate quat * vec
ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return out;
};
/**
* Perform some operation over an array of vec4s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec4.forEach = (function() {
var vec = vec4.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 4;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec4} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec4.str = function (a) {
return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec4 = vec4;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2x2 Matrix
* @name mat2
*/
var mat2 = {};
/**
* Creates a new identity mat2
*
* @returns {mat2} a new 2x2 matrix
*/
mat2.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Creates a new mat2 initialized with values from an existing matrix
*
* @param {mat2} a matrix to clone
* @returns {mat2} a new 2x2 matrix
*/
mat2.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Copy the values from one mat2 to another
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Set a mat2 to the identity matrix
*
* @param {mat2} out the receiving matrix
* @returns {mat2} out
*/
mat2.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Transpose the values of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a1 = a[1];
out[1] = a[2];
out[2] = a1;
} else {
out[0] = a[0];
out[1] = a[2];
out[2] = a[1];
out[3] = a[3];
}
return out;
};
/**
* Inverts a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.invert = function(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
// Calculate the determinant
det = a0 * a3 - a2 * a1;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = a3 * det;
out[1] = -a1 * det;
out[2] = -a2 * det;
out[3] = a0 * det;
return out;
};
/**
* Calculates the adjugate of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.adjoint = function(out, a) {
// Caching this value is nessecary if out == a
var a0 = a[0];
out[0] = a[3];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a0;
return out;
};
/**
* Calculates the determinant of a mat2
*
* @param {mat2} a the source matrix
* @returns {Number} determinant of a
*/
mat2.determinant = function (a) {
return a[0] * a[3] - a[2] * a[1];
};
/**
* Multiplies two mat2's
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @returns {mat2} out
*/
mat2.multiply = function (out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
return out;
};
/**
* Alias for {@link mat2.multiply}
* @function
*/
mat2.mul = mat2.multiply;
/**
* Rotates a mat2 by the given angle
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2} out
*/
mat2.rotate = function (out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
return out;
};
/**
* Scales the mat2 by the dimensions in the given vec2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2} out
**/
mat2.scale = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
return out;
};
/**
* Returns a string representation of a mat2
*
* @param {mat2} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat2.str = function (a) {
return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
/**
* Returns Frobenius norm of a mat2
*
* @param {mat2} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat2.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
};
/**
* Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
* @param {mat2} L the lower triangular matrix
* @param {mat2} D the diagonal matrix
* @param {mat2} U the upper triangular matrix
* @param {mat2} a the input matrix to factorize
*/
mat2.LDU = function (L, D, U, a) {
L[2] = a[2]/a[0];
U[0] = a[0];
U[1] = a[1];
U[3] = a[3] - L[2] * U[1];
return [L, D, U];
};
if(typeof(exports) !== 'undefined') {
exports.mat2 = mat2;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2x3 Matrix
* @name mat2d
*
* @description
* A mat2d contains six elements defined as:
* <pre>
* [a, c, tx,
* b, d, ty]
* </pre>
* This is a short form for the 3x3 matrix:
* <pre>
* [a, c, tx,
* b, d, ty,
* 0, 0, 1]
* </pre>
* The last row is ignored so the array is shorter and operations are faster.
*/
var mat2d = {};
/**
* Creates a new identity mat2d
*
* @returns {mat2d} a new 2x3 matrix
*/
mat2d.create = function() {
var out = new GLMAT_ARRAY_TYPE(6);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
};
/**
* Creates a new mat2d initialized with values from an existing matrix
*
* @param {mat2d} a matrix to clone
* @returns {mat2d} a new 2x3 matrix
*/
mat2d.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(6);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
};
/**
* Copy the values from one mat2d to another
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
mat2d.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
};
/**
* Set a mat2d to the identity matrix
*
* @param {mat2d} out the receiving matrix
* @returns {mat2d} out
*/
mat2d.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
};
/**
* Inverts a mat2d
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
mat2d.invert = function(out, a) {
var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
atx = a[4], aty = a[5];
var det = aa * ad - ab * ac;
if(!det){
return null;
}
det = 1.0 / det;
out[0] = ad * det;
out[1] = -ab * det;
out[2] = -ac * det;
out[3] = aa * det;
out[4] = (ac * aty - ad * atx) * det;
out[5] = (ab * atx - aa * aty) * det;
return out;
};
/**
* Calculates the determinant of a mat2d
*
* @param {mat2d} a the source matrix
* @returns {Number} determinant of a
*/
mat2d.determinant = function (a) {
return a[0] * a[3] - a[1] * a[2];
};
/**
* Multiplies two mat2d's
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @returns {mat2d} out
*/
mat2d.multiply = function (out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
out[4] = a0 * b4 + a2 * b5 + a4;
out[5] = a1 * b4 + a3 * b5 + a5;
return out;
};
/**
* Alias for {@link mat2d.multiply}
* @function
*/
mat2d.mul = mat2d.multiply;
/**
* Rotates a mat2d by the given angle
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2d} out
*/
mat2d.rotate = function (out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
out[4] = a4;
out[5] = a5;
return out;
};
/**
* Scales the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2d} out
**/
mat2d.scale = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
out[4] = a4;
out[5] = a5;
return out;
};
/**
* Translates the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to translate the matrix by
* @returns {mat2d} out
**/
mat2d.translate = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
v0 = v[0], v1 = v[1];
out[0] = a0;
out[1] = a1;
out[2] = a2;
out[3] = a3;
out[4] = a0 * v0 + a2 * v1 + a4;
out[5] = a1 * v0 + a3 * v1 + a5;
return out;
};
/**
* Returns a string representation of a mat2d
*
* @param {mat2d} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat2d.str = function (a) {
return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ')';
};
/**
* Returns Frobenius norm of a mat2d
*
* @param {mat2d} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat2d.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
};
if(typeof(exports) !== 'undefined') {
exports.mat2d = mat2d;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 3x3 Matrix
* @name mat3
*/
var mat3 = {};
/**
* Creates a new identity mat3
*
* @returns {mat3} a new 3x3 matrix
*/
mat3.create = function() {
var out = new GLMAT_ARRAY_TYPE(9);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
};
/**
* Copies the upper-left 3x3 values into the given mat3.
*
* @param {mat3} out the receiving 3x3 matrix
* @param {mat4} a the source 4x4 matrix
* @returns {mat3} out
*/
mat3.fromMat4 = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[4];
out[4] = a[5];
out[5] = a[6];
out[6] = a[8];
out[7] = a[9];
out[8] = a[10];
return out;
};
/**
* Creates a new mat3 initialized with values from an existing matrix
*
* @param {mat3} a matrix to clone
* @returns {mat3} a new 3x3 matrix
*/
mat3.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(9);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Copy the values from one mat3 to another
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Set a mat3 to the identity matrix
*
* @param {mat3} out the receiving matrix
* @returns {mat3} out
*/
mat3.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
};
/**
* Transpose the values of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a12 = a[5];
out[1] = a[3];
out[2] = a[6];
out[3] = a01;
out[5] = a[7];
out[6] = a02;
out[7] = a12;
} else {
out[0] = a[0];
out[1] = a[3];
out[2] = a[6];
out[3] = a[1];
out[4] = a[4];
out[5] = a[7];
out[6] = a[2];
out[7] = a[5];
out[8] = a[8];
}
return out;
};
/**
* Inverts a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.invert = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
b01 = a22 * a11 - a12 * a21,
b11 = -a22 * a10 + a12 * a20,
b21 = a21 * a10 - a11 * a20,
// Calculate the determinant
det = a00 * b01 + a01 * b11 + a02 * b21;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = b01 * det;
out[1] = (-a22 * a01 + a02 * a21) * det;
out[2] = (a12 * a01 - a02 * a11) * det;
out[3] = b11 * det;
out[4] = (a22 * a00 - a02 * a20) * det;
out[5] = (-a12 * a00 + a02 * a10) * det;
out[6] = b21 * det;
out[7] = (-a21 * a00 + a01 * a20) * det;
out[8] = (a11 * a00 - a01 * a10) * det;
return out;
};
/**
* Calculates the adjugate of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.adjoint = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8];
out[0] = (a11 * a22 - a12 * a21);
out[1] = (a02 * a21 - a01 * a22);
out[2] = (a01 * a12 - a02 * a11);
out[3] = (a12 * a20 - a10 * a22);
out[4] = (a00 * a22 - a02 * a20);
out[5] = (a02 * a10 - a00 * a12);
out[6] = (a10 * a21 - a11 * a20);
out[7] = (a01 * a20 - a00 * a21);
out[8] = (a00 * a11 - a01 * a10);
return out;
};
/**
* Calculates the determinant of a mat3
*
* @param {mat3} a the source matrix
* @returns {Number} determinant of a
*/
mat3.determinant = function (a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8];
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
};
/**
* Multiplies two mat3's
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @returns {mat3} out
*/
mat3.multiply = function (out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
b00 = b[0], b01 = b[1], b02 = b[2],
b10 = b[3], b11 = b[4], b12 = b[5],
b20 = b[6], b21 = b[7], b22 = b[8];
out[0] = b00 * a00 + b01 * a10 + b02 * a20;
out[1] = b00 * a01 + b01 * a11 + b02 * a21;
out[2] = b00 * a02 + b01 * a12 + b02 * a22;
out[3] = b10 * a00 + b11 * a10 + b12 * a20;
out[4] = b10 * a01 + b11 * a11 + b12 * a21;
out[5] = b10 * a02 + b11 * a12 + b12 * a22;
out[6] = b20 * a00 + b21 * a10 + b22 * a20;
out[7] = b20 * a01 + b21 * a11 + b22 * a21;
out[8] = b20 * a02 + b21 * a12 + b22 * a22;
return out;
};
/**
* Alias for {@link mat3.multiply}
* @function
*/
mat3.mul = mat3.multiply;
/**
* Translate a mat3 by the given vector
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to translate
* @param {vec2} v vector to translate by
* @returns {mat3} out
*/
mat3.translate = function(out, a, v) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
x = v[0], y = v[1];
out[0] = a00;
out[1] = a01;
out[2] = a02;
out[3] = a10;
out[4] = a11;
out[5] = a12;
out[6] = x * a00 + y * a10 + a20;
out[7] = x * a01 + y * a11 + a21;
out[8] = x * a02 + y * a12 + a22;
return out;
};
/**
* Rotates a mat3 by the given angle
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat3} out
*/
mat3.rotate = function (out, a, rad) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = c * a00 + s * a10;
out[1] = c * a01 + s * a11;
out[2] = c * a02 + s * a12;
out[3] = c * a10 - s * a00;
out[4] = c * a11 - s * a01;
out[5] = c * a12 - s * a02;
out[6] = a20;
out[7] = a21;
out[8] = a22;
return out;
};
/**
* Scales the mat3 by the dimensions in the given vec2
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat3} out
**/
mat3.scale = function(out, a, v) {
var x = v[0], y = v[1];
out[0] = x * a[0];
out[1] = x * a[1];
out[2] = x * a[2];
out[3] = y * a[3];
out[4] = y * a[4];
out[5] = y * a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Copies the values from a mat2d into a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat2d} a the matrix to copy
* @returns {mat3} out
**/
mat3.fromMat2d = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = 0;
out[3] = a[2];
out[4] = a[3];
out[5] = 0;
out[6] = a[4];
out[7] = a[5];
out[8] = 1;
return out;
};
/**
* Calculates a 3x3 matrix from the given quaternion
*
* @param {mat3} out mat3 receiving operation result
* @param {quat} q Quaternion to create matrix from
*
* @returns {mat3} out
*/
mat3.fromQuat = function (out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
yx = y * x2,
yy = y * y2,
zx = z * x2,
zy = z * y2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - yy - zz;
out[3] = yx - wz;
out[6] = zx + wy;
out[1] = yx + wz;
out[4] = 1 - xx - zz;
out[7] = zy - wx;
out[2] = zx - wy;
out[5] = zy + wx;
out[8] = 1 - xx - yy;
return out;
};
/**
* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
*
* @param {mat3} out mat3 receiving operation result
* @param {mat4} a Mat4 to derive the normal matrix from
*
* @returns {mat3} out
*/
mat3.normalFromMat4 = function (out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
// Calculate the determinant
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
return out;
};
/**
* Returns a string representation of a mat3
*
* @param {mat3} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat3.str = function (a) {
return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
a[6] + ', ' + a[7] + ', ' + a[8] + ')';
};
/**
* Returns Frobenius norm of a mat3
*
* @param {mat3} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat3.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
};
if(typeof(exports) !== 'undefined') {
exports.mat3 = mat3;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 4x4 Matrix
* @name mat4
*/
var mat4 = {};
/**
* Creates a new identity mat4
*
* @returns {mat4} a new 4x4 matrix
*/
mat4.create = function() {
var out = new GLMAT_ARRAY_TYPE(16);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Creates a new mat4 initialized with values from an existing matrix
*
* @param {mat4} a matrix to clone
* @returns {mat4} a new 4x4 matrix
*/
mat4.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(16);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Copy the values from one mat4 to another
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Set a mat4 to the identity matrix
*
* @param {mat4} out the receiving matrix
* @returns {mat4} out
*/
mat4.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Transpose the values of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a03 = a[3],
a12 = a[6], a13 = a[7],
a23 = a[11];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a01;
out[6] = a[9];
out[7] = a[13];
out[8] = a02;
out[9] = a12;
out[11] = a[14];
out[12] = a03;
out[13] = a13;
out[14] = a23;
} else {
out[0] = a[0];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a[1];
out[5] = a[5];
out[6] = a[9];
out[7] = a[13];
out[8] = a[2];
out[9] = a[6];
out[10] = a[10];
out[11] = a[14];
out[12] = a[3];
out[13] = a[7];
out[14] = a[11];
out[15] = a[15];
}
return out;
};
/**
* Inverts a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.invert = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
// Calculate the determinant
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return out;
};
/**
* Calculates the adjugate of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.adjoint = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
return out;
};
/**
* Calculates the determinant of a mat4
*
* @param {mat4} a the source matrix
* @returns {Number} determinant of a
*/
mat4.determinant = function (a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32;
// Calculate the determinant
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
};
/**
* Multiplies two mat4's
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @returns {mat4} out
*/
mat4.multiply = function (out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
// Cache only the current line of the second matrix
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
return out;
};
/**
* Alias for {@link mat4.multiply}
* @function
*/
mat4.mul = mat4.multiply;
/**
* Translate a mat4 by the given vector
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to translate
* @param {vec3} v vector to translate by
* @returns {mat4} out
*/
mat4.translate = function (out, a, v) {
var x = v[0], y = v[1], z = v[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
};
/**
* Scales the mat4 by the dimensions in the given vec3
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to scale
* @param {vec3} v the vec3 to scale the matrix by
* @returns {mat4} out
**/
mat4.scale = function(out, a, v) {
var x = v[0], y = v[1], z = v[2];
out[0] = a[0] * x;
out[1] = a[1] * x;
out[2] = a[2] * x;
out[3] = a[3] * x;
out[4] = a[4] * y;
out[5] = a[5] * y;
out[6] = a[6] * y;
out[7] = a[7] * y;
out[8] = a[8] * z;
out[9] = a[9] * z;
out[10] = a[10] * z;
out[11] = a[11] * z;
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Rotates a mat4 by the given angle
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @param {vec3} axis the axis to rotate around
* @returns {mat4} out
*/
mat4.rotate = function (out, a, rad, axis) {
var x = axis[0], y = axis[1], z = axis[2],
len = Math.sqrt(x * x + y * y + z * z),
s, c, t,
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23,
b00, b01, b02,
b10, b11, b12,
b20, b21, b22;
if (Math.abs(len) < GLMAT_EPSILON) { return null; }
len = 1 / len;
x *= len;
y *= len;
z *= len;
s = Math.sin(rad);
c = Math.cos(rad);
t = 1 - c;
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
// Construct the elements of the rotation matrix
b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
// Perform rotation-specific matrix multiplication
out[0] = a00 * b00 + a10 * b01 + a20 * b02;
out[1] = a01 * b00 + a11 * b01 + a21 * b02;
out[2] = a02 * b00 + a12 * b01 + a22 * b02;
out[3] = a03 * b00 + a13 * b01 + a23 * b02;
out[4] = a00 * b10 + a10 * b11 + a20 * b12;
out[5] = a01 * b10 + a11 * b11 + a21 * b12;
out[6] = a02 * b10 + a12 * b11 + a22 * b12;
out[7] = a03 * b10 + a13 * b11 + a23 * b12;
out[8] = a00 * b20 + a10 * b21 + a20 * b22;
out[9] = a01 * b20 + a11 * b21 + a21 * b22;
out[10] = a02 * b20 + a12 * b21 + a22 * b22;
out[11] = a03 * b20 + a13 * b21 + a23 * b22;
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
return out;
};
/**
* Rotates a matrix by the given angle around the X axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateX = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a10 = a[4],
a11 = a[5],
a12 = a[6],
a13 = a[7],
a20 = a[8],
a21 = a[9],
a22 = a[10],
a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[4] = a10 * c + a20 * s;
out[5] = a11 * c + a21 * s;
out[6] = a12 * c + a22 * s;
out[7] = a13 * c + a23 * s;
out[8] = a20 * c - a10 * s;
out[9] = a21 * c - a11 * s;
out[10] = a22 * c - a12 * s;
out[11] = a23 * c - a13 * s;
return out;
};
/**
* Rotates a matrix by the given angle around the Y axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateY = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a00 = a[0],
a01 = a[1],
a02 = a[2],
a03 = a[3],
a20 = a[8],
a21 = a[9],
a22 = a[10],
a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c - a20 * s;
out[1] = a01 * c - a21 * s;
out[2] = a02 * c - a22 * s;
out[3] = a03 * c - a23 * s;
out[8] = a00 * s + a20 * c;
out[9] = a01 * s + a21 * c;
out[10] = a02 * s + a22 * c;
out[11] = a03 * s + a23 * c;
return out;
};
/**
* Rotates a matrix by the given angle around the Z axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateZ = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a00 = a[0],
a01 = a[1],
a02 = a[2],
a03 = a[3],
a10 = a[4],
a11 = a[5],
a12 = a[6],
a13 = a[7];
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c + a10 * s;
out[1] = a01 * c + a11 * s;
out[2] = a02 * c + a12 * s;
out[3] = a03 * c + a13 * s;
out[4] = a10 * c - a00 * s;
out[5] = a11 * c - a01 * s;
out[6] = a12 * c - a02 * s;
out[7] = a13 * c - a03 * s;
return out;
};
/**
* Creates a matrix from a quaternion rotation and vector translation
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, vec);
* var quatMat = mat4.create();
* quat4.toMat4(quat, quatMat);
* mat4.multiply(dest, quatMat);
*
* @param {mat4} out mat4 receiving operation result
* @param {quat4} q Rotation quaternion
* @param {vec3} v Translation vector
* @returns {mat4} out
*/
mat4.fromRotationTranslation = function (out, q, v) {
// Quaternion math
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
xy = x * y2,
xz = x * z2,
yy = y * y2,
yz = y * z2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - (yy + zz);
out[1] = xy + wz;
out[2] = xz - wy;
out[3] = 0;
out[4] = xy - wz;
out[5] = 1 - (xx + zz);
out[6] = yz + wx;
out[7] = 0;
out[8] = xz + wy;
out[9] = yz - wx;
out[10] = 1 - (xx + yy);
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
};
mat4.fromQuat = function (out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
yx = y * x2,
yy = y * y2,
zx = z * x2,
zy = z * y2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - yy - zz;
out[1] = yx + wz;
out[2] = zx - wy;
out[3] = 0;
out[4] = yx - wz;
out[5] = 1 - xx - zz;
out[6] = zy + wx;
out[7] = 0;
out[8] = zx + wy;
out[9] = zy - wx;
out[10] = 1 - xx - yy;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Generates a frustum matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {Number} left Left bound of the frustum
* @param {Number} right Right bound of the frustum
* @param {Number} bottom Bottom bound of the frustum
* @param {Number} top Top bound of the frustum
* @param {Number} near Near bound of the frustum
* @param {Number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.frustum = function (out, left, right, bottom, top, near, far) {
var rl = 1 / (right - left),
tb = 1 / (top - bottom),
nf = 1 / (near - far);
out[0] = (near * 2) * rl;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = (near * 2) * tb;
out[6] = 0;
out[7] = 0;
out[8] = (right + left) * rl;
out[9] = (top + bottom) * tb;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (far * near * 2) * nf;
out[15] = 0;
return out;
};
/**
* Generates a perspective projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} fovy Vertical field of view in radians
* @param {number} aspect Aspect ratio. typically viewport width/height
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.perspective = function (out, fovy, aspect, near, far) {
var f = 1.0 / Math.tan(fovy / 2),
nf = 1 / (near - far);
out[0] = f / aspect;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = f;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (2 * far * near) * nf;
out[15] = 0;
return out;
};
/**
* Generates a orthogonal projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} left Left bound of the frustum
* @param {number} right Right bound of the frustum
* @param {number} bottom Bottom bound of the frustum
* @param {number} top Top bound of the frustum
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.ortho = function (out, left, right, bottom, top, near, far) {
var lr = 1 / (left - right),
bt = 1 / (bottom - top),
nf = 1 / (near - far);
out[0] = -2 * lr;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = -2 * bt;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 2 * nf;
out[11] = 0;
out[12] = (left + right) * lr;
out[13] = (top + bottom) * bt;
out[14] = (far + near) * nf;
out[15] = 1;
return out;
};
/**
* Generates a look-at matrix with the given eye position, focal point, and up axis
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {vec3} eye Position of the viewer
* @param {vec3} center Point the viewer is looking at
* @param {vec3} up vec3 pointing up
* @returns {mat4} out
*/
mat4.lookAt = function (out, eye, center, up) {
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
Math.abs(eyey - centery) < GLMAT_EPSILON &&
Math.abs(eyez - centerz) < GLMAT_EPSILON) {
return mat4.identity(out);
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
return out;
};
/**
* Returns a string representation of a mat4
*
* @param {mat4} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat4.str = function (a) {
return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
};
/**
* Returns Frobenius norm of a mat4
*
* @param {mat4} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat4.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
};
if(typeof(exports) !== 'undefined') {
exports.mat4 = mat4;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class Quaternion
* @name quat
*/
var quat = {};
/**
* Creates a new identity quat
*
* @returns {quat} a new quaternion
*/
quat.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Sets a quaternion to represent the shortest rotation from one
* vector to another.
*
* Both vectors are assumed to be unit length.
*
* @param {quat} out the receiving quaternion.
* @param {vec3} a the initial vector
* @param {vec3} b the destination vector
* @returns {quat} out
*/
quat.rotationTo = (function() {
var tmpvec3 = vec3.create();
var xUnitVec3 = vec3.fromValues(1,0,0);
var yUnitVec3 = vec3.fromValues(0,1,0);
return function(out, a, b) {
var dot = vec3.dot(a, b);
if (dot < -0.999999) {
vec3.cross(tmpvec3, xUnitVec3, a);
if (vec3.length(tmpvec3) < 0.000001)
vec3.cross(tmpvec3, yUnitVec3, a);
vec3.normalize(tmpvec3, tmpvec3);
quat.setAxisAngle(out, tmpvec3, Math.PI);
return out;
} else if (dot > 0.999999) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
} else {
vec3.cross(tmpvec3, a, b);
out[0] = tmpvec3[0];
out[1] = tmpvec3[1];
out[2] = tmpvec3[2];
out[3] = 1 + dot;
return quat.normalize(out, out);
}
};
})();
/**
* Sets the specified quaternion with values corresponding to the given
* axes. Each axis is a vec3 and is expected to be unit length and
* perpendicular to all other specified axes.
*
* @param {vec3} view the vector representing the viewing direction
* @param {vec3} right the vector representing the local "right" direction
* @param {vec3} up the vector representing the local "up" direction
* @returns {quat} out
*/
quat.setAxes = (function() {
var matr = mat3.create();
return function(out, view, right, up) {
matr[0] = right[0];
matr[3] = right[1];
matr[6] = right[2];
matr[1] = up[0];
matr[4] = up[1];
matr[7] = up[2];
matr[2] = -view[0];
matr[5] = -view[1];
matr[8] = -view[2];
return quat.normalize(out, quat.fromMat3(out, matr));
};
})();
/**
* Creates a new quat initialized with values from an existing quaternion
*
* @param {quat} a quaternion to clone
* @returns {quat} a new quaternion
* @function
*/
quat.clone = vec4.clone;
/**
* Creates a new quat initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} a new quaternion
* @function
*/
quat.fromValues = vec4.fromValues;
/**
* Copy the values from one quat to another
*
* @param {quat} out the receiving quaternion
* @param {quat} a the source quaternion
* @returns {quat} out
* @function
*/
quat.copy = vec4.copy;
/**
* Set the components of a quat to the given values
*
* @param {quat} out the receiving quaternion
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} out
* @function
*/
quat.set = vec4.set;
/**
* Set a quat to the identity quaternion
*
* @param {quat} out the receiving quaternion
* @returns {quat} out
*/
quat.identity = function(out) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Sets a quat from the given angle and rotation axis,
* then returns it.
*
* @param {quat} out the receiving quaternion
* @param {vec3} axis the axis around which to rotate
* @param {Number} rad the angle in radians
* @returns {quat} out
**/
quat.setAxisAngle = function(out, axis, rad) {
rad = rad * 0.5;
var s = Math.sin(rad);
out[0] = s * axis[0];
out[1] = s * axis[1];
out[2] = s * axis[2];
out[3] = Math.cos(rad);
return out;
};
/**
* Adds two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
* @function
*/
quat.add = vec4.add;
/**
* Multiplies two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
*/
quat.multiply = function(out, a, b) {
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = b[0], by = b[1], bz = b[2], bw = b[3];
out[0] = ax * bw + aw * bx + ay * bz - az * by;
out[1] = ay * bw + aw * by + az * bx - ax * bz;
out[2] = az * bw + aw * bz + ax * by - ay * bx;
out[3] = aw * bw - ax * bx - ay * by - az * bz;
return out;
};
/**
* Alias for {@link quat.multiply}
* @function
*/
quat.mul = quat.multiply;
/**
* Scales a quat by a scalar number
*
* @param {quat} out the receiving vector
* @param {quat} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {quat} out
* @function
*/
quat.scale = vec4.scale;
/**
* Rotates a quaternion by the given angle about the X axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateX = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + aw * bx;
out[1] = ay * bw + az * bx;
out[2] = az * bw - ay * bx;
out[3] = aw * bw - ax * bx;
return out;
};
/**
* Rotates a quaternion by the given angle about the Y axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateY = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
by = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw - az * by;
out[1] = ay * bw + aw * by;
out[2] = az * bw + ax * by;
out[3] = aw * bw - ay * by;
return out;
};
/**
* Rotates a quaternion by the given angle about the Z axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateZ = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bz = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + ay * bz;
out[1] = ay * bw - ax * bz;
out[2] = az * bw + aw * bz;
out[3] = aw * bw - az * bz;
return out;
};
/**
* Calculates the W component of a quat from the X, Y, and Z components.
* Assumes that quaternion is 1 unit in length.
* Any existing W component will be ignored.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate W component of
* @returns {quat} out
*/
quat.calculateW = function (out, a) {
var x = a[0], y = a[1], z = a[2];
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
return out;
};
/**
* Calculates the dot product of two quat's
*
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {Number} dot product of a and b
* @function
*/
quat.dot = vec4.dot;
/**
* Performs a linear interpolation between two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {quat} out
* @function
*/
quat.lerp = vec4.lerp;
/**
* Performs a spherical linear interpolation between two quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {quat} out
*/
quat.slerp = function (out, a, b, t) {
// benchmarks:
// http://jsperf.com/quaternion-slerp-implementations
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = b[0], by = b[1], bz = b[2], bw = b[3];
var omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = ax * bx + ay * by + az * bz + aw * bw;
// adjust signs (if necessary)
if ( cosom < 0.0 ) {
cosom = -cosom;
bx = - bx;
by = - by;
bz = - bz;
bw = - bw;
}
// calculate coefficients
if ( (1.0 - cosom) > 0.000001 ) {
// standard case (slerp)
omega = Math.acos(cosom);
sinom = Math.sin(omega);
scale0 = Math.sin((1.0 - t) * omega) / sinom;
scale1 = Math.sin(t * omega) / sinom;
} else {
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0 - t;
scale1 = t;
}
// calculate final values
out[0] = scale0 * ax + scale1 * bx;
out[1] = scale0 * ay + scale1 * by;
out[2] = scale0 * az + scale1 * bz;
out[3] = scale0 * aw + scale1 * bw;
return out;
};
/**
* Calculates the inverse of a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate inverse of
* @returns {quat} out
*/
quat.invert = function(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
invDot = dot ? 1.0/dot : 0;
// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
out[0] = -a0*invDot;
out[1] = -a1*invDot;
out[2] = -a2*invDot;
out[3] = a3*invDot;
return out;
};
/**
* Calculates the conjugate of a quat
* If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate conjugate of
* @returns {quat} out
*/
quat.conjugate = function (out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a[3];
return out;
};
/**
* Calculates the length of a quat
*
* @param {quat} a vector to calculate length of
* @returns {Number} length of a
* @function
*/
quat.length = vec4.length;
/**
* Alias for {@link quat.length}
* @function
*/
quat.len = quat.length;
/**
* Calculates the squared length of a quat
*
* @param {quat} a vector to calculate squared length of
* @returns {Number} squared length of a
* @function
*/
quat.squaredLength = vec4.squaredLength;
/**
* Alias for {@link quat.squaredLength}
* @function
*/
quat.sqrLen = quat.squaredLength;
/**
* Normalize a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quaternion to normalize
* @returns {quat} out
* @function
*/
quat.normalize = vec4.normalize;
/**
* Creates a quaternion from the given 3x3 rotation matrix.
*
* NOTE: The resultant quaternion is not normalized, so you should be sure
* to renormalize the quaternion yourself where necessary.
*
* @param {quat} out the receiving quaternion
* @param {mat3} m rotation matrix
* @returns {quat} out
* @function
*/
quat.fromMat3 = function(out, m) {
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
// article "Quaternion Calculus and Fast Animation".
var fTrace = m[0] + m[4] + m[8];
var fRoot;
if ( fTrace > 0.0 ) {
// |w| > 1/2, may as well choose w > 1/2
fRoot = Math.sqrt(fTrace + 1.0); // 2w
out[3] = 0.5 * fRoot;
fRoot = 0.5/fRoot; // 1/(4w)
out[0] = (m[7]-m[5])*fRoot;
out[1] = (m[2]-m[6])*fRoot;
out[2] = (m[3]-m[1])*fRoot;
} else {
// |w| <= 1/2
var i = 0;
if ( m[4] > m[0] )
i = 1;
if ( m[8] > m[i*3+i] )
i = 2;
var j = (i+1)%3;
var k = (i+2)%3;
fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
out[i] = 0.5 * fRoot;
fRoot = 0.5 / fRoot;
out[3] = (m[k*3+j] - m[j*3+k]) * fRoot;
out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
}
return out;
};
/**
* Returns a string representation of a quatenion
*
* @param {quat} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
quat.str = function (a) {
return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.quat = quat;
}
;
})(shim.exports);
})(this);
},{}],105:[function(require,module,exports){
'use strict';
function constant(value) {
return function() {
return value;
}
}
function interpolateNumber(a, b, t) {
return (a * (1 - t)) + (b * t);
}
function interpolateArray(a, b, t) {
var result = [];
for (var i = 0; i < a.length; i++) {
result[i] = interpolateNumber(a[i], b[i], t);
}
return result;
}
exports['interpolated'] = function(f) {
if (!f.stops) {
return constant(f);
}
var stops = f.stops,
base = f.base || 1,
interpolate = Array.isArray(stops[0][1]) ? interpolateArray : interpolateNumber;
return function(z) {
// find the two stops which the current z is between
var low, high;
for (var i = 0; i < stops.length; i++) {
var stop = stops[i];
if (stop[0] <= z) {
low = stop;
}
if (stop[0] > z) {
high = stop;
break;
}
}
if (low && high) {
var zoomDiff = high[0] - low[0],
zoomProgress = z - low[0],
t = base === 1 ?
zoomProgress / zoomDiff :
(Math.pow(base, zoomProgress) - 1) / (Math.pow(base, zoomDiff) - 1);
return interpolate(low[1], high[1], t);
} else if (low) {
return low[1];
} else if (high) {
return high[1];
}
};
};
exports['piecewise-constant'] = function(f) {
if (!f.stops) {
return constant(f);
}
var stops = f.stops;
return function(z) {
for (var i = 0; i < stops.length; i++) {
if (stops[i][0] > z) {
return stops[i === 0 ? 0 : i - 1][1];
}
}
return stops[stops.length - 1][1];
}
};
},{}],106:[function(require,module,exports){
'use strict';
var reference = require('../../reference/latest.js');
var validate = require('./parsed');
module.exports = function(style) {
return validate(style, reference);
};
},{"../../reference/latest.js":108,"./parsed":107}],107:[function(require,module,exports){
'use strict';
var parseCSSColor = require('csscolorparser').parseCSSColor;
var format = require('util').format;
module.exports = function(style, reference) {
var constants = style.constants || {},
layers = {},
errors = [];
function error(key, val /*, message, ...*/) {
var err = {
message: (key ? key + ': ' : '') +
format.apply(format, Array.prototype.slice.call(arguments, 2))
};
if (val !== null && val !== undefined && val.__line__) {
err.line = val.__line__;
}
errors.push(err);
}
// Main recursive validation function. Tracks:
//
// - key: string representing location of validation in style tree. Used only
// for more informative error reporting.
// - val: current value from style being evaluated. May be anything from a
// high level object that needs to be descended into deeper or a simple
// scalar value.
// - spec: current spec being evaluated. Tracks val.
//
function validate(key, val, spec) {
var type = typeof_(val);
// Constants
if (type === 'string' && val[0] === '@') {
if (!(val in constants)) {
return error(key, val, 'constant "%s" not found', val);
}
val = constants[val];
type = typeof_(val);
}
// Functions
if (spec.function && type === 'object') {
return validate.function(key, val, spec);
}
if (spec.type) {
var validator = validate[spec.type];
if (validator) {
return validator(key, val, spec);
}
spec = reference[spec.type];
}
validate.object(key, val, spec);
}
validate.constants = function(key, val) {
var type = typeof_(val);
if (type !== 'object') {
return error(key, val, 'object expected, %s found', type);
}
for (var k in val) {
if (k[0] !== '@') {
error(key + '.' + k, val[k], 'constants must start with "@"');
}
}
};
validate.source = function(key, val) {
if (!val.type) {
error(key, val, '"type" is required');
return;
}
var type = unbundle(val.type);
switch (type) {
case 'vector':
case 'raster':
validate.object(key, val, reference.source_tile);
if ('url' in val) {
for (var prop in val) {
if (['type', 'url', 'tileSize'].indexOf(prop) < 0) {
error(key + '.' + prop, val[prop], 'a source with a "url" property may not include a "%s" property', prop);
}
}
}
break;
case 'geojson':
validate.object(key, val, reference.source_geojson);
break;
case 'video':
validate.object(key, val, reference.source_video);
break;
default:
validate.enum(key + '.type', val.type, {values: ['vector', 'raster', 'geojson', 'video']});
}
};
validate.layer = function(key, val) {
if (!val.type && !val.ref) {
error(key, val, 'either "type" or "ref" is required');
}
var type = unbundle(val.type),
ref = unbundle(val.ref);
if (val.id) {
if (layers[val.id]) {
error(key, val.id, 'duplicate layer id "%s", previously used at line %d', val.id, layers[val.id]);
} else {
layers[val.id] = val.id.__line__;
}
}
if ('ref' in val) {
['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) {
if (p in val) {
error(key, val[p], '"%s" is prohibited for ref layers', p);
}
});
var parent;
style.layers.forEach(function(layer) {
if (layer.id == ref) parent = layer;
});
if (!parent) {
error(key, val.ref, 'ref layer "%s" not found', ref);
} else if (parent.ref) {
error(key, val.ref, 'ref cannot reference another ref layer');
} else {
type = parent.type;
}
} else if (type !== 'background') {
if (!val.source) {
error(key, val, 'missing required property "source"');
} else {
var source = style.sources[val.source];
if (!source) {
error(key, val.source, 'source "%s" not found', val.source);
} else if (source.type == 'vector' && type == 'raster') {
error(key, val.source, 'layer "%s" requires a raster source', val.id);
} else if (source.type == 'raster' && type != 'raster') {
error(key, val.source, 'layer "%s" requires a vector source', val.id);
}
}
}
validate.object(key, val, reference.layer, {
filter: validate.filter,
layout: function(key, val) {
var spec = reference['layout_' + type];
return type && spec && validate(key, val, spec);
},
paint: function(key, val) {
var spec = reference['paint_' + type];
return type && spec && validate(key, val, spec);
}
});
};
validate.object = function (key, val, spec, validators) {
validators = validators || {};
var type = typeof_(val);
if (type !== 'object') {
return error(key, val, 'object expected, %s found', type);
}
for (var k in val) {
var speckey = k.split('.')[0]; // treat 'paint.*' as 'paint'
var def = spec[speckey] || spec['*'];
var transition = speckey.match(/^(.*)-transition$/);
if (def) {
(validators[speckey] || validate)((key ? key + '.' : key) + k, val[k], def);
} else if (transition && spec[transition[1]] && spec[transition[1]].transition) {
validate((key ? key + '.' : key) + k, val[k], reference.transition);
// tolerate root-level extra keys & arbitrary layer properties
} else if (key !== '' && key.split('.').length !== 1) {
error(key, val[k], 'unknown property "%s"', k);
}
}
for (var l in spec) {
if (spec[l].required && spec[l]['default'] === undefined && val[l] === undefined) {
error(key, val, 'missing required property "%s"', l);
}
}
};
validate.array = function (key, val, spec, validator) {
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (spec.length && val.length !== spec.length) {
return error(key, val, 'array length %d expected, length %d found', spec.length, val.length);
}
var value = {
"type": spec.value
};
if (style.version < 7) {
value.function = spec.function;
}
if (typeof_(spec.value) === 'object') {
value = spec.value;
}
for (var i = 0; i < val.length; i++) {
(validator || validate)(key + '[' + i + ']', val[i], value);
}
};
validate.filter = function(key, val) {
var type;
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (val.length < 1) {
return error(key, val, 'filter array must have at least 1 element');
}
validate.enum(key + '[0]', val[0], reference.filter_operator);
switch (unbundle(val[0])) {
case '<':
case '<=':
case '>':
case '>=':
if (val.length >= 2 && val[1] == '$type') {
error(key, val, '"$type" cannot be use with operator "%s"', val[0]);
}
/* falls through */
case '==':
case '!=':
if (val.length != 3) {
error(key, val, 'filter array for operator "%s" must have 3 elements', val[0]);
}
/* falls through */
case 'in':
case '!in':
if (val.length >= 2) {
type = typeof_(val[1]);
if (type !== 'string') {
error(key + '[1]', val[1], 'string expected, %s found', type);
} else if (val[1][0] === '@') {
error(key + '[1]', val[1], 'filter key cannot be a constant');
}
}
for (var i = 2; i < val.length; i++) {
type = typeof_(val[i]);
if (val[1] == '$type') {
validate.enum(key + '[' + i + ']', val[i], reference.geometry_type);
} else if (type === 'string' && val[i][0] === '@') {
error(key + '[' + i + ']', val[i], 'filter value cannot be a constant');
} else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
error(key + '[' + i + ']', val[i], 'string, number, or boolean expected, %s found', type);
}
}
break;
case 'any':
case 'all':
case 'none':
for (i = 1; i < val.length; i++) {
validate.filter(key + '[' + i + ']', val[i]);
}
break;
}
};
validate.function = function(key, val, spec) {
validate.object(key, val, reference.function, {
stops: function (key, val, arraySpec) {
var lastStop = -Infinity;
validate.array(key, val, arraySpec, function validateStop(key, val) {
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (val.length !== 2) {
return error(key, val, 'array length %d expected, length %d found', 2, val.length);
}
validate(key + '[0]', val[0], {type: 'number'});
validate(key + '[1]', val[1], spec);
if (typeof_(val[0]) === 'number') {
if (spec.function === 'piecewise-constant' && val[0] % 1 !== 0) {
error(key + '[0]', val[0], 'zoom level for piecewise-constant functions must be an integer');
}
if (val[0] < lastStop) {
error(key + '[0]', val[0], 'array stops must appear in ascending order');
}
lastStop = val[0];
}
});
if (typeof_(val) === 'array' && val.length === 0) {
error(key, val, 'array must have at least one stop');
}
}
});
};
validate.enum = function (key, val, spec) {
if (spec.values.indexOf(unbundle(val)) === -1) {
error(key, val, 'expected one of [%s], %s found', spec.values.join(', '), val);
}
};
validate.color = function(key, val) {
var type = typeof_(val);
if (type !== 'string') {
error(key, val, 'color expected, %s found', type);
} else if (parseCSSColor(val) === null) {
error(key, val, 'color expected, "%s" found', val);
}
};
function typeValidator(expected) {
return function(key, val, spec) {
var actual = typeof_(val);
if (actual !== expected) {
error(key, val, '%s expected, %s found', expected, actual);
}
if ('minimum' in spec && val < spec.minimum) {
error(key, val, '%s is less than the minimum value %s', val, spec.minimum);
}
if ('maximum' in spec && val > spec.maximum) {
error(key, val, '%s is greater than the maximum value %s', val, spec.maximum);
}
};
}
validate.number = typeValidator('number');
validate.string = typeValidator('string');
validate.boolean = typeValidator('boolean');
validate['*'] = function() {};
validate('', style, reference.$root);
return errors;
};
function typeof_(val) {
if (val instanceof Number)
return 'number';
if (val instanceof String)
return 'string';
if (val instanceof Boolean)
return 'boolean';
if (Array.isArray(val))
return 'array';
if (val === null)
return 'null';
return typeof val;
}
function unbundle(_) {
if (_ instanceof Number ||
_ instanceof String ||
_ instanceof Boolean) {
return _.valueOf();
} else {
return _;
}
}
},{"csscolorparser":97,"util":124}],108:[function(require,module,exports){
module.exports = require('./v7.json');
},{"./v7.json":109}],109:[function(require,module,exports){
module.exports={
"$version": 7,
"$root": {
"version": {
"required": true,
"type": "enum",
"values": [
7
],
"doc": "Stylesheet version number. Must be 7."
},
"name": {
"type": "string",
"doc": "A human-readable name for the style."
},
"constants": {
"type": "constants",
"doc": "An object of constants to be referenced in layers."
},
"sources": {
"required": true,
"type": "sources",
"doc": "Data source specifications."
},
"sprite": {
"type": "string",
"doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended."
},
"glyphs": {
"type": "string",
"doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}."
},
"transition": {
"type": "transition",
"doc": "A global transition definition to use as a default across properties."
},
"layers": {
"required": true,
"type": "array",
"value": "layer",
"doc": "Layers will be drawn in the order of this array."
}
},
"constants": {
"*": {
"type": "*",
"doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol."
}
},
"sources": {
"*": {
"type": "source",
"doc": "Specification of a data source. For vector and raster sources, either TileJSON or a URL to a TileJSON must be provided. For GeoJSON and video sources, a URL must be provided."
}
},
"source": [
"source_tile",
"source_geojson",
"source_video"
],
"source_tile": {
"type": {
"required": true,
"type": "enum",
"values": [
"vector",
"raster"
],
"doc": "The data type of the source."
},
"url": {
"type": "string",
"doc": "A URL to a TileJSON resource. Supported protocols are `http:`, `https:`, and `mapbox://<mapid>`."
},
"tiles": {
"type": "array",
"value": "string",
"doc": "An array of one or more tile source URLs, as in the TileJSON spec."
},
"minzoom": {
"type": "number",
"default": 0,
"doc": "Minimum zoom level for which tiles are available, as in the TileJSON spec."
},
"maxzoom": {
"type": "number",
"default": 22,
"doc": "Maximum zoom level for which tiles are available, as in the TileJSON spec. Data from tiles at the maxzoom are used when displaying the map at higher zoom levels."
},
"tileSize": {
"type": "number",
"default": 512,
"units": "pixels",
"doc": "The minimum visual size to display tiles for this layer. Only configurable for raster layers."
},
"*": {
"type": "*",
"doc": "Other keys to configure the data source."
}
},
"source_geojson": {
"type": {
"required": true,
"type": "enum",
"values": [
"geojson"
]
},
"data": {
"type": "*"
}
},
"source_video": {
"type": {
"required": true,
"type": "enum",
"values": [
"video"
]
},
"url": {
"required": true,
"type": "array",
"value": "string",
"doc": "URLs to video content in order of preferred format."
},
"coordinates": {
"required": true,
"type": "array",
"length": 4,
"value": {
"type": "array",
"length": 2,
"value": "number"
}
}
},
"layer": {
"id": {
"type": "string",
"doc": "Unique layer name."
},
"type": {
"type": "enum",
"values": [
"fill",
"line",
"symbol",
"raster",
"background"
],
"doc": "Rendering type of this layer."
},
"ref": {
"type": "string",
"doc": "References another layer to copy `type`, `source`, `source-layer`, `minzoom`, `maxzoom`, `filter`, and `layout` properties from. This allows the layers to share processing and be more efficient."
},
"source": {
"type": "string",
"doc": "Name of a source description to be used for this layer."
},
"source-layer": {
"type": "string",
"doc": "Layer to use from a vector tile source. Required if the source supports multiple layers."
},
"minzoom": {
"type": "number",
"minimum": 0,
"maximum": 22,
"doc": "The minimum zoom level on which the layer gets parsed and appears on."
},
"maxzoom": {
"type": "number",
"minimum": 0,
"maximum": 22,
"doc": "The maximum zoom level on which the layer gets parsed and appears on."
},
"interactive": {
"type": "boolean",
"doc": "Enable querying of feature data from this layer for interactivity.",
"default": false
},
"filter": {
"type": "filter",
"doc": "A expression specifying conditions on source features. Only features that match the filter are displayed."
},
"layout": {
"type": "layout",
"doc": "Layout properties for the layer."
},
"paint": {
"type": "paint",
"doc": "Default paint properties for this layer."
},
"paint.*": {
"type": "paint",
"doc": "Class-specific paint properties for this layer. The class name is the part after the first dot."
}
},
"layout": [
"layout_fill",
"layout_line",
"layout_symbol",
"layout_raster",
"layout_background"
],
"layout_background": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_fill": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_line": {
"line-cap": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"butt",
"round",
"square"
],
"default": "butt",
"doc": "The display of line endings."
},
"line-join": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"bevel",
"round",
"miter"
],
"default": "miter",
"doc": "The display of lines when joining."
},
"line-miter-limit": {
"type": "number",
"default": 2,
"function": "interpolated",
"doc": "Used to automatically convert miter joins to bevel joins for sharp angles.",
"requires": [
{
"line-join": "miter"
}
]
},
"line-round-limit": {
"type": "number",
"default": 1,
"function": "interpolated",
"doc": "Used to automatically convert round joins to miter joins for shallow angles.",
"requires": [
{
"line-join": "round"
}
]
},
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_symbol": {
"symbol-placement": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"point",
"line"
],
"default": "point",
"doc": "Label placement relative to its geometry. `line` can only be used on LineStrings and Polygons."
},
"symbol-min-distance": {
"type": "number",
"default": 250,
"minimum": 1,
"function": "interpolated",
"units": "pixels",
"doc": "Minimum distance between two symbol anchors.",
"requires": [
{
"symbol-placement": "line"
}
]
},
"symbol-avoid-edges": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer."
},
"icon-allow-overlap": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon will be visible even if it collides with other icons and text.",
"requires": [
"icon-image"
]
},
"icon-ignore-placement": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon won't affect placement of other icons and text.",
"requires": [
"icon-image"
]
},
"icon-optional": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbol will appear without its icon, in spaces where the icon would make it too large to fit.",
"requires": [
"icon-image",
"text-field"
]
},
"icon-rotation-alignment": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"default": "viewport",
"doc": "Orientation of icon when map is rotated.",
"requires": [
"icon-image"
]
},
"icon-max-size": {
"type": "number",
"default": 1,
"minimum": 0,
"function": "interpolated",
"doc": "The maximum factor to scale the icon.",
"requires": [
"icon-image"
]
},
"icon-image": {
"type": "string",
"function": "piecewise-constant",
"doc": "A string with {tokens} replaced, referencing the data property to pull from.",
"tokens": true
},
"icon-rotate": {
"type": "number",
"default": 0,
"period": 360,
"function": "interpolated",
"units": "degrees",
"doc": "Rotates the icon clockwise.",
"requires": [
"icon-image"
]
},
"icon-padding": {
"type": "number",
"default": 2,
"minimum": 0,
"function": "interpolated",
"units": "pixels",
"doc": "Padding value around icon bounding box to avoid icon collisions.",
"requires": [
"icon-image"
]
},
"icon-keep-upright": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon may be flipped to prevent it from being rendered upside-down",
"requires": [
"icon-image",
{
"icon-rotation-alignment": "map"
}
]
},
"icon-offset": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"doc": "Icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"icon-image"
]
},
"text-rotation-alignment": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"default": "viewport",
"doc": "Orientation of icon or text when map is rotated.",
"requires": [
"text-field"
]
},
"text-field": {
"type": "string",
"function": "piecewise-constant",
"default": "",
"tokens": true,
"doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}."
},
"text-font": {
"type": "string",
"function": "piecewise-constant",
"default": "Open Sans Regular, Arial Unicode MS Regular",
"doc": "Font stack to use for displaying text.",
"requires": [
"text-field"
]
},
"text-max-size": {
"type": "number",
"default": 16,
"minimum": 0,
"units": "pixels",
"function": "interpolated",
"doc": "The maximum size text will be laid out, to calculate collisions with.",
"requires": [
"text-field"
]
},
"text-max-width": {
"type": "number",
"default": 15,
"minimum": 0,
"units": "em",
"function": "interpolated",
"doc": "The maximum line width for text wrapping.",
"requires": [
"text-field"
]
},
"text-line-height": {
"type": "number",
"default": 1.2,
"units": "em",
"function": "interpolated",
"doc": "Text leading value for multi-line text.",
"requires": [
"text-field"
]
},
"text-letter-spacing": {
"type": "number",
"default": 0,
"units": "em",
"function": "interpolated",
"doc": "Text kerning value.",
"requires": [
"text-field"
]
},
"text-justify": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"left",
"center",
"right"
],
"default": "center",
"doc": "Text justification options.",
"requires": [
"text-field"
]
},
"text-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"center",
"left",
"right",
"top",
"bottom",
"top-left",
"top-right",
"bottom-left",
"bottom-right"
],
"default": "center",
"doc": "Which part of the text to place closest to the anchor.",
"requires": [
"text-field"
]
},
"text-max-angle": {
"type": "number",
"default": 45,
"units": "degrees",
"function": "interpolated",
"doc": "Maximum angle change between adjacent characters.",
"requires": [
"text-field",
{
"symbol-placement": "line"
}
]
},
"text-rotate": {
"type": "number",
"default": 0,
"period": 360,
"units": "degrees",
"function": "interpolated",
"doc": "Rotates the text clockwise.",
"requires": [
"text-field"
]
},
"text-padding": {
"type": "number",
"default": 2,
"minimum": 0,
"units": "pixels",
"function": "interpolated",
"doc": "Padding value around text bounding box to avoid label collisions.",
"requires": [
"text-field"
]
},
"text-keep-upright": {
"type": "boolean",
"function": "piecewise-constant",
"default": true,
"doc": "If true, the text may be flipped vertically to prevent it from being rendered upside-down.",
"requires": [
"text-field",
{
"text-rotation-alignment": "map"
}
]
},
"text-transform": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"none",
"uppercase",
"lowercase"
],
"default": "none",
"doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property.",
"requires": [
"text-field"
]
},
"text-offset": {
"type": "array",
"doc": "Specifies the distance that text is offset from its anchor horizontally and vertically.",
"value": "number",
"units": "ems",
"function": "interpolated",
"length": 2,
"default": [
0,
0
],
"requires": [
"text-field"
]
},
"text-allow-overlap": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the text will be visible even if it collides with other icons and labels.",
"requires": [
"text-field"
]
},
"text-ignore-placement": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the text won't affect placement of other icons and labels.",
"requires": [
"text-field"
]
},
"text-optional": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbol will appear without its text, in spaces where the text would make it too large to fit.",
"requires": [
"text-field",
"icon-image"
]
},
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_raster": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"filter": {
"type": "array",
"value": "*"
},
"filter_operator": {
"type": "enum",
"values": [
"==",
"!=",
">",
">=",
"<",
"<=",
"in",
"!in",
"all",
"any",
"none"
]
},
"geometry_type": {
"type": "enum",
"values": [
"Point",
"LineString",
"Polygon"
]
},
"function": {
"stops": {
"type": "array",
"required": true,
"doc": "An array of stops.",
"value": "function_stop"
},
"base": {
"type": "number",
"default": 1,
"minimum": 0,
"doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly."
}
},
"function_stop": {
"type": "array",
"minimum": 0,
"maximum": 22,
"value": [
"number",
"color"
],
"length": 2,
"doc": "Zoom level and value pair."
},
"paint": [
"paint_fill",
"paint_line",
"paint_symbol",
"paint_raster",
"paint_background"
],
"paint_fill": {
"fill-antialias": {
"type": "boolean",
"function": "piecewise-constant",
"default": true,
"doc": "Whether or not the fill should be antialiased."
},
"fill-opacity": {
"type": "number",
"function": "interpolated",
"default": 1,
"minimum": 0,
"maximum": 1,
"doc": "The opacity given to the fill color.",
"transition": true
},
"fill-color": {
"type": "color",
"default": "#000000",
"doc": "The color of the fill.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "fill-image"
}
]
},
"fill-outline-color": {
"type": "color",
"doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "fill-image"
},
{
"fill-antialias": true
}
]
},
"fill-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively."
},
"fill-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"fill-translate"
]
},
"fill-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Name of image in sprite to use for drawing image fills."
}
},
"paint_line": {
"line-opacity": {
"type": "number",
"doc": "The opacity at which the line will be drawn.",
"function": "interpolated",
"default": 1,
"minimum": 0,
"maximum": 1,
"transition": true
},
"line-color": {
"type": "color",
"doc": "The color with which the line will be drawn.",
"default": "#000000",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "line-image"
}
]
},
"line-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively."
},
"line-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"line-translate"
]
},
"line-width": {
"type": "number",
"default": 1,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Stroke thickness."
},
"line-gap-width": {
"type": "number",
"default": 0,
"minimum": 0,
"doc": "Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.",
"function": "interpolated",
"transition": true,
"units": "pixels"
},
"line-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Blur applied to the line, in pixels."
},
"line-dasharray": {
"type": "array",
"function": "piecewise-constant",
"value": "number",
"doc": "Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.",
"minimum": 0,
"transition": true,
"units": "line widths",
"requires": [
{
"!": "line-image"
}
]
},
"line-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Name of image in sprite to use for drawing image lines."
}
},
"paint_symbol": {
"icon-opacity": {
"doc": "The opacity at which the icon will be drawn.",
"type": "number",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true,
"requires": [
"icon-image"
]
},
"icon-size": {
"type": "number",
"default": 1,
"function": "interpolated",
"transition": true,
"doc": "Scale factor for icon. 1 is original size, 3 triples the size.",
"requires": [
"icon-image"
]
},
"icon-color": {
"type": "color",
"default": "#000000",
"function": "interpolated",
"transition": true,
"doc": "The color of the icon. This can only be used with sdf icons.",
"requires": [
"icon-image"
]
},
"icon-halo-color": {
"type": "color",
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"transition": true,
"doc": "The color of the icon's halo. Icon halos can only be used with sdf icons.",
"requires": [
"icon-image"
]
},
"icon-halo-width": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the icon outline.",
"requires": [
"icon-image"
]
},
"icon-halo-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Fade out the halo towards the outside.",
"requires": [
"icon-image"
]
},
"icon-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "An icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"icon-image"
]
},
"icon-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"icon-image",
"icon-translate"
]
},
"text-opacity": {
"type": "number",
"doc": "The opacity at which the text will be drawn.",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true,
"requires": [
"text-field"
]
},
"text-size": {
"type": "number",
"default": 16,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Font size. If unspecified, the text will be as big as allowed by the layer definition.",
"requires": [
"text-field"
]
},
"text-color": {
"type": "color",
"doc": "The color with which the text will be drawn.",
"default": "#000000",
"function": "interpolated",
"transition": true,
"requires": [
"text-field"
]
},
"text-halo-color": {
"type": "color",
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"transition": true,
"doc": "The color of the text's halo, which helps it stand out from backgrounds.",
"requires": [
"text-field"
]
},
"text-halo-width": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.",
"requires": [
"text-field"
]
},
"text-halo-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The halo's fadeout distance towards the outside.",
"requires": [
"text-field"
]
},
"text-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Label offset. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"text-field"
]
},
"text-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"text-field",
"text-translate"
]
}
},
"paint_raster": {
"raster-opacity": {
"type": "number",
"doc": "The opacity at which the image will be drawn.",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-hue-rotate": {
"type": "number",
"default": 0,
"period": 360,
"function": "interpolated",
"transition": true,
"units": "degrees",
"doc": "Rotates hues around the color wheel."
},
"raster-brightness-min": {
"type": "number",
"function": "interpolated",
"doc": "Increase or reduce the brightness of the image. The value is the minimum brightness.",
"default": 0,
"minimum": 0,
"maximum": 1,
"transition": true
},
"raster-brightness-max": {
"type": "number",
"function": "interpolated",
"doc": "Increase or reduce the brightness of the image. The value is the maximum brightness.",
"default": 1,
"minimum": 0,
"maximum": 1,
"transition": true
},
"raster-saturation": {
"type": "number",
"doc": "Increase or reduce the saturation of the image.",
"default": 0,
"minimum": -1,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-contrast": {
"type": "number",
"doc": "Increase or reduce the contrast of the image.",
"default": 0,
"minimum": -1,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-fade-duration": {
"type": "number",
"default": 300,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "milliseconds",
"doc": "Fade duration when a new tile is added."
}
},
"paint_background": {
"background-color": {
"type": "color",
"default": "#000000",
"doc": "The color with which the background will be drawn.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "background-image"
}
]
},
"background-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Optionally an image which is drawn as the background."
},
"background-opacity": {
"type": "number",
"default": 1,
"minimum": 0,
"maximum": 1,
"doc": "The opacity at which the background will be drawn.",
"function": "interpolated",
"transition": true
}
},
"transition": {
"duration": {
"type": "number",
"default": 300,
"minimum": 0,
"units": "milliseconds",
"doc": "Time allotted for transitions to complete."
},
"delay": {
"type": "number",
"default": 0,
"minimum": 0,
"units": "milliseconds",
"doc": "Length of time before a transition begins."
}
}
}
},{}],110:[function(require,module,exports){
'use strict';
// lightweight Buffer shim for pbf browser build
// based on code from github.com/feross/buffer (MIT-licensed)
module.exports = Buffer;
var ieee754 = require('ieee754');
var BufferMethods;
function Buffer(length) {
var arr;
if (length && length.length) {
arr = length;
length = arr.length;
}
var buf = new Uint8Array(length || 0);
if (arr) buf.set(arr);
buf.readUInt32LE = BufferMethods.readUInt32LE;
buf.writeUInt32LE = BufferMethods.writeUInt32LE;
buf.readInt32LE = BufferMethods.readInt32LE;
buf.writeInt32LE = BufferMethods.writeInt32LE;
buf.readFloatLE = BufferMethods.readFloatLE;
buf.writeFloatLE = BufferMethods.writeFloatLE;
buf.readDoubleLE = BufferMethods.readDoubleLE;
buf.writeDoubleLE = BufferMethods.writeDoubleLE;
buf.toString = BufferMethods.toString;
buf.write = BufferMethods.write;
buf.slice = BufferMethods.slice;
buf.copy = BufferMethods.copy;
buf._isBuffer = true;
return buf;
}
var lastStr, lastStrEncoded;
BufferMethods = {
readUInt32LE: function(pos) {
return ((this[pos]) |
(this[pos + 1] << 8) |
(this[pos + 2] << 16)) +
(this[pos + 3] * 0x1000000);
},
writeUInt32LE: function(val, pos) {
this[pos] = val;
this[pos + 1] = (val >>> 8);
this[pos + 2] = (val >>> 16);
this[pos + 3] = (val >>> 24);
},
readInt32LE: function(pos) {
return ((this[pos]) |
(this[pos + 1] << 8) |
(this[pos + 2] << 16)) +
(this[pos + 3] << 24);
},
readFloatLE: function(pos) { return ieee754.read(this, pos, true, 23, 4); },
readDoubleLE: function(pos) { return ieee754.read(this, pos, true, 52, 8); },
writeFloatLE: function(val, pos) { return ieee754.write(this, val, pos, true, 23, 4); },
writeDoubleLE: function(val, pos) { return ieee754.write(this, val, pos, true, 52, 8); },
toString: function(encoding, start, end) {
var str = '',
tmp = '';
start = start || 0;
end = Math.min(this.length, end || this.length);
for (var i = start; i < end; i++) {
var ch = this[i];
if (ch <= 0x7F) {
str += decodeURIComponent(tmp) + String.fromCharCode(ch);
tmp = '';
} else {
tmp += '%' + ch.toString(16);
}
}
str += decodeURIComponent(tmp);
return str;
},
write: function(str, pos) {
var bytes = str === lastStr ? lastStrEncoded : encodeString(str);
for (var i = 0; i < bytes.length; i++) {
this[pos + i] = bytes[i];
}
},
slice: function(start, end) {
return this.subarray(start, end);
},
copy: function(buf, pos) {
pos = pos || 0;
for (var i = 0; i < this.length; i++) {
buf[pos + i] = this[i];
}
}
};
BufferMethods.writeInt32LE = BufferMethods.writeUInt32LE;
Buffer.byteLength = function(str) {
lastStr = str;
lastStrEncoded = encodeString(str);
return lastStrEncoded.length;
};
Buffer.isBuffer = function(buf) {
return !!(buf && buf._isBuffer);
};
function encodeString(str) {
var length = str.length,
bytes = [];
for (var i = 0, c, lead; i < length; i++) {
c = str.charCodeAt(i); // code point
if (c > 0xD7FF && c < 0xE000) {
if (lead) {
if (c < 0xDC00) {
bytes.push(0xEF, 0xBF, 0xBD);
lead = c;
continue;
} else {
c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
lead = null;
}
} else {
if (c > 0xDBFF || (i + 1 === length)) bytes.push(0xEF, 0xBF, 0xBD);
else lead = c;
continue;
}
} else if (lead) {
bytes.push(0xEF, 0xBF, 0xBD);
lead = null;
}
if (c < 0x80) bytes.push(c);
else if (c < 0x800) bytes.push(c >> 0x6 | 0xC0, c & 0x3F | 0x80);
else if (c < 0x10000) bytes.push(c >> 0xC | 0xE0, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80);
else bytes.push(c >> 0x12 | 0xF0, c >> 0xC & 0x3F | 0x80, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80);
}
return bytes;
}
},{"ieee754":112}],111:[function(require,module,exports){
(function (global){
'use strict';
module.exports = Pbf;
var Buffer = global.Buffer || require('./buffer');
function Pbf(buf) {
this.buf = !Buffer.isBuffer(buf) ? new Buffer(buf || 0) : buf;
this.pos = 0;
this.length = this.buf.length;
}
Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32,
POW_2_63 = Math.pow(2, 63);
Pbf.prototype = {
destroy: function() {
this.buf = null;
},
// === READING =================================================================
readFields: function(readField, result, end) {
end = end || this.length;
while (this.pos < end) {
var val = this.readVarint(),
tag = val >> 3,
startPos = this.pos;
readField(tag, result, this);
if (this.pos === startPos) this.skip(val);
}
return result;
},
readMessage: function(readField, result) {
return this.readFields(readField, result, this.readVarint() + this.pos);
},
readFixed32: function() {
var val = this.buf.readUInt32LE(this.pos);
this.pos += 4;
return val;
},
readSFixed32: function() {
var val = this.buf.readInt32LE(this.pos);
this.pos += 4;
return val;
},
// 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
readFixed64: function() {
var val = this.buf.readUInt32LE(this.pos) + this.buf.readUInt32LE(this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readSFixed64: function() {
var val = this.buf.readUInt32LE(this.pos) + this.buf.readInt32LE(this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readFloat: function() {
var val = this.buf.readFloatLE(this.pos);
this.pos += 4;
return val;
},
readDouble: function() {
var val = this.buf.readDoubleLE(this.pos);
this.pos += 8;
return val;
},
readVarint: function() {
var buf = this.buf,
val, b, b0, b1, b2, b3;
b0 = buf[this.pos++]; if (b0 < 0x80) return b0; b0 = b0 & 0x7f;
b1 = buf[this.pos++]; if (b1 < 0x80) return b0 | b1 << 7; b1 = (b1 & 0x7f) << 7;
b2 = buf[this.pos++]; if (b2 < 0x80) return b0 | b1 | b2 << 14; b2 = (b2 & 0x7f) << 14;
b3 = buf[this.pos++]; if (b3 < 0x80) return b0 | b1 | b2 | b3 << 21;
val = b0 | b1 | b2 | (b3 & 0x7f) << 21;
b = buf[this.pos++]; val += (b & 0x7f) * 0x10000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x800000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x40000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x2000000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x100000000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x8000000000000000; if (b < 0x80) return val;
throw new Error('Expected varint not more than 10 bytes');
},
readVarint64: function() {
var startPos = this.pos,
val = this.readVarint();
if (val < POW_2_63) return val;
var pos = this.pos - 2;
while (this.buf[pos] === 0xff) pos--;
if (pos < startPos) pos = startPos;
val = 0;
for (var i = 0; i < pos - startPos + 1; i++) {
var b = ~this.buf[startPos + i] & 0x7f;
val += i < 4 ? b << i * 7 : b * Math.pow(2, i * 7);
}
return -val - 1;
},
readSVarint: function() {
var num = this.readVarint();
return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
},
readBoolean: function() {
return Boolean(this.readVarint());
},
readString: function() {
var end = this.readVarint() + this.pos,
str = this.buf.toString('utf8', this.pos, end);
this.pos = end;
return str;
},
readBytes: function() {
var end = this.readVarint() + this.pos,
buffer = this.buf.slice(this.pos, end);
this.pos = end;
return buffer;
},
// verbose for performance reasons; doesn't affect gzipped size
readPackedVarint: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readVarint());
return arr;
},
readPackedSVarint: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSVarint());
return arr;
},
readPackedBoolean: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readBoolean());
return arr;
},
readPackedFloat: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFloat());
return arr;
},
readPackedDouble: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readDouble());
return arr;
},
readPackedFixed32: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFixed32());
return arr;
},
readPackedSFixed32: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSFixed32());
return arr;
},
readPackedFixed64: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFixed64());
return arr;
},
readPackedSFixed64: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSFixed64());
return arr;
},
skip: function(val) {
var type = val & 0x7;
if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {}
else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;
else if (type === Pbf.Fixed32) this.pos += 4;
else if (type === Pbf.Fixed64) this.pos += 8;
else throw new Error('Unimplemented type: ' + type);
},
// === WRITING =================================================================
writeTag: function(tag, type) {
this.writeVarint((tag << 3) | type);
},
realloc: function(min) {
var length = this.length || 16;
while (length < this.pos + min) length *= 2;
if (length !== this.length) {
var buf = new Buffer(length);
this.buf.copy(buf);
this.buf = buf;
this.length = length;
}
},
finish: function() {
this.length = this.pos;
this.pos = 0;
return this.buf.slice(0, this.length);
},
writeFixed32: function(val) {
this.realloc(4);
this.buf.writeUInt32LE(val, this.pos);
this.pos += 4;
},
writeSFixed32: function(val) {
this.realloc(4);
this.buf.writeInt32LE(val, this.pos);
this.pos += 4;
},
writeFixed64: function(val) {
this.realloc(8);
this.buf.writeInt32LE(val & -1, this.pos);
this.buf.writeUInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeSFixed64: function(val) {
this.realloc(8);
this.buf.writeInt32LE(val & -1, this.pos);
this.buf.writeInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeVarint: function(val) {
val = +val;
if (val <= 0x7f) {
this.realloc(1);
this.buf[this.pos++] = val;
} else if (val <= 0x3fff) {
this.realloc(2);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f);
} else if (val <= 0x1fffff) {
this.realloc(3);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 14) & 0x7f);
} else if (val <= 0xfffffff) {
this.realloc(4);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 14) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 21) & 0x7f);
} else {
var pos = this.pos;
while (val >= 0x80) {
this.realloc(1);
this.buf[this.pos++] = (val & 0xff) | 0x80;
val /= 0x80;
}
this.realloc(1);
this.buf[this.pos++] = val | 0;
if (this.pos - pos > 10) throw new Error('Given varint doesn\'t fit into 10 bytes');
}
},
writeSVarint: function(val) {
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
},
writeBoolean: function(val) {
this.writeVarint(Boolean(val));
},
writeString: function(str) {
str = String(str);
var bytes = Buffer.byteLength(str);
this.writeVarint(bytes);
this.realloc(bytes);
this.buf.write(str, this.pos);
this.pos += bytes;
},
writeFloat: function(val) {
this.realloc(4);
this.buf.writeFloatLE(val, this.pos);
this.pos += 4;
},
writeDouble: function(val) {
this.realloc(8);
this.buf.writeDoubleLE(val, this.pos);
this.pos += 8;
},
writeBytes: function(buffer) {
var len = buffer.length;
this.writeVarint(len);
this.realloc(len);
for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
},
writeMessage: function(tag, fn, obj) {
this.writeTag(tag, Pbf.Bytes);
this.pos++; // reserve 1 byte for short message length
// write the message directly to the buffer and see how much was written
var startPos = this.pos;
fn(obj, this);
var len = this.pos - startPos;
var varintLen =
len <= 0x7f ? 1 :
len <= 0x3fff ? 2 :
len <= 0x1fffff ? 3 :
len <= 0xfffffff ? 4 : Math.ceil(Math.log(len) / (Math.LN2 * 7));
// if 1 byte isn't enough for encoding message length, shift the data to the right
if (varintLen > 1) {
this.realloc(varintLen - 1);
for (var i = this.pos - 1; i >= startPos; i--) this.buf[i + varintLen - 1] = this.buf[i];
}
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
},
writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); },
writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); },
writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); },
writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); },
writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); },
writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); },
writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); },
writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); },
writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); },
writeBytesField: function(tag, buffer) {
this.writeTag(tag, Pbf.Bytes);
this.writeBytes(buffer);
},
writeFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFixed32(val);
},
writeSFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeSFixed32(val);
},
writeFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeFixed64(val);
},
writeSFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeSFixed64(val);
},
writeVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeVarint(val);
},
writeSVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeSVarint(val);
},
writeStringField: function(tag, str) {
this.writeTag(tag, Pbf.Bytes);
this.writeString(str);
},
writeFloatField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFloat(val);
},
writeDoubleField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeDouble(val);
},
writeBooleanField: function(tag, val) {
this.writeVarintField(tag, Boolean(val));
}
};
function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]); }
function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]); }
function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]); }
function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]); }
function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]); }
function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]); }
function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); }
function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]); }
function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./buffer":110}],112:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isLE ? (nBytes - 1) : 0,
d = isLE ? -1 : 1,
s = buffer[offset + i]
i += d
e = s & ((1 << (-nBits)) - 1)
s >>= (-nBits)
nBits += eLen
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
m = e & ((1 << (-nBits)) - 1)
e >>= (-nBits)
nBits += mLen
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
if (e === 0) {
e = 1 - eBias
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity)
} else {
m = m + Math.pow(2, mLen)
e = e - eBias
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isLE ? 0 : (nBytes - 1),
d = isLE ? 1 : -1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
value = Math.abs(value)
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0
e = eMax
} else {
e = Math.floor(Math.log(value) / Math.LN2)
if (value * (c = Math.pow(2, -e)) < 1) {
e--
c *= 2
}
if (e + eBias >= 1) {
value += rt / c
} else {
value += rt * Math.pow(2, 1 - eBias)
}
if (value * c >= 2) {
e++
c /= 2
}
if (e + eBias >= eMax) {
m = 0
e = eMax
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen)
e = e + eBias
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
e = 0
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
e = (e << mLen) | m
eLen += mLen
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
buffer[offset + i - d] |= s * 128
}
},{}],113:[function(require,module,exports){
'use strict';
module.exports = Point;
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
clone: function() { return new Point(this.x, this.y); },
add: function(p) { return this.clone()._add(p); },
sub: function(p) { return this.clone()._sub(p); },
mult: function(k) { return this.clone()._mult(k); },
div: function(k) { return this.clone()._div(k); },
rotate: function(a) { return this.clone()._rotate(a); },
matMult: function(m) { return this.clone()._matMult(m); },
unit: function() { return this.clone()._unit(); },
perp: function() { return this.clone()._perp(); },
round: function() { return this.clone()._round(); },
mag: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
equals: function(p) {
return this.x === p.x &&
this.y === p.y;
},
dist: function(p) {
return Math.sqrt(this.distSqr(p));
},
distSqr: function(p) {
var dx = p.x - this.x,
dy = p.y - this.y;
return dx * dx + dy * dy;
},
angle: function() {
return Math.atan2(this.y, this.x);
},
angleTo: function(b) {
return Math.atan2(this.y - b.y, this.x - b.x);
},
angleWith: function(b) {
return this.angleWithSep(b.x, b.y);
},
// Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ.
angleWithSep: function(x, y) {
return Math.atan2(
this.x * y - this.y * x,
this.x * x + this.y * y);
},
_matMult: function(m) {
var x = m[0] * this.x + m[1] * this.y,
y = m[2] * this.x + m[3] * this.y;
this.x = x;
this.y = y;
return this;
},
_add: function(p) {
this.x += p.x;
this.y += p.y;
return this;
},
_sub: function(p) {
this.x -= p.x;
this.y -= p.y;
return this;
},
_mult: function(k) {
this.x *= k;
this.y *= k;
return this;
},
_div: function(k) {
this.x /= k;
this.y /= k;
return this;
},
_unit: function() {
this._div(this.mag());
return this;
},
_perp: function() {
var y = this.y;
this.y = this.x;
this.x = -y;
return this;
},
_rotate: function(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = cos * this.x - sin * this.y,
y = sin * this.x + cos * this.y;
this.x = x;
this.y = y;
return this;
},
_round: function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
}
};
// constructs Point from an array if necessary
Point.convert = function (a) {
if (a instanceof Point) {
return a;
}
if (Array.isArray(a)) {
return new Point(a[0], a[1]);
}
return a;
};
},{}],114:[function(require,module,exports){
/*
(c) 2013, Vladimir Agafonkin
RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
https://github.com/mourner/rbush
*/
(function () { 'use strict';
function rbush(maxEntries, format) {
// jshint newcap: false, validthis: true
if (!(this instanceof rbush)) return new rbush(maxEntries, format);
// max entries in a node is 9 by default; min node fill is 40% for best performance
this._maxEntries = Math.max(4, maxEntries || 9);
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
if (format) {
this._initFormat(format);
}
this.clear();
}
rbush.prototype = {
all: function () {
return this._all(this.data, []);
},
search: function (bbox) {
var node = this.data,
result = [],
toBBox = this.toBBox;
if (!intersects(bbox, node.bbox)) return result;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child.bbox;
if (intersects(bbox, childBBox)) {
if (node.leaf) result.push(child);
else if (contains(bbox, childBBox)) this._all(child, result);
else nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return result;
},
collides: function (bbox) {
var node = this.data,
toBBox = this.toBBox;
if (!intersects(bbox, node.bbox)) return false;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child.bbox;
if (intersects(bbox, childBBox)) {
if (node.leaf || contains(bbox, childBBox)) return true;
nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return false;
},
load: function (data) {
if (!(data && data.length)) return this;
if (data.length < this._minEntries) {
for (var i = 0, len = data.length; i < len; i++) {
this.insert(data[i]);
}
return this;
}
// recursively build the tree with the given data from stratch using OMT algorithm
var node = this._build(data.slice(), 0, data.length - 1, 0);
if (!this.data.children.length) {
// save as is if tree is empty
this.data = node;
} else if (this.data.height === node.height) {
// split root if trees have the same height
this._splitRoot(this.data, node);
} else {
if (this.data.height < node.height) {
// swap trees if inserted one is bigger
var tmpNode = this.data;
this.data = node;
node = tmpNode;
}
// insert the small tree into the large tree at appropriate level
this._insert(node, this.data.height - node.height - 1, true);
}
return this;
},
insert: function (item) {
if (item) this._insert(item, this.data.height - 1);
return this;
},
clear: function () {
this.data = {
children: [],
height: 1,
bbox: empty(),
leaf: true
};
return this;
},
remove: function (item) {
if (!item) return this;
var node = this.data,
bbox = this.toBBox(item),
path = [],
indexes = [],
i, parent, index, goingUp;
// depth-first iterative tree traversal
while (node || path.length) {
if (!node) { // go up
node = path.pop();
parent = path[path.length - 1];
i = indexes.pop();
goingUp = true;
}
if (node.leaf) { // check current node
index = node.children.indexOf(item);
if (index !== -1) {
// item found, remove the item and condense tree upwards
node.children.splice(index, 1);
path.push(node);
this._condense(path);
return this;
}
}
if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down
path.push(node);
indexes.push(i);
i = 0;
parent = node;
node = node.children[0];
} else if (parent) { // go right
i++;
node = parent.children[i];
goingUp = false;
} else node = null; // nothing found
}
return this;
},
toBBox: function (item) { return item; },
compareMinX: function (a, b) { return a[0] - b[0]; },
compareMinY: function (a, b) { return a[1] - b[1]; },
toJSON: function () { return this.data; },
fromJSON: function (data) {
this.data = data;
return this;
},
_all: function (node, result) {
var nodesToSearch = [];
while (node) {
if (node.leaf) result.push.apply(result, node.children);
else nodesToSearch.push.apply(nodesToSearch, node.children);
node = nodesToSearch.pop();
}
return result;
},
_build: function (items, left, right, height) {
var N = right - left + 1,
M = this._maxEntries,
node;
if (N <= M) {
// reached leaf level; return leaf
node = {
children: items.slice(left, right + 1),
height: 1,
bbox: null,
leaf: true
};
calcBBox(node, this.toBBox);
return node;
}
if (!height) {
// target height of the bulk-loaded tree
height = Math.ceil(Math.log(N) / Math.log(M));
// target number of root entries to maximize storage utilization
M = Math.ceil(N / Math.pow(M, height - 1));
}
// TODO eliminate recursion?
node = {
children: [],
height: height,
bbox: null
};
// split the items into M mostly square tiles
var N2 = Math.ceil(N / M),
N1 = N2 * Math.ceil(Math.sqrt(M)),
i, j, right2, right3;
multiSelect(items, left, right, N1, this.compareMinX);
for (i = left; i <= right; i += N1) {
right2 = Math.min(i + N1 - 1, right);
multiSelect(items, i, right2, N2, this.compareMinY);
for (j = i; j <= right2; j += N2) {
right3 = Math.min(j + N2 - 1, right2);
// pack each entry recursively
node.children.push(this._build(items, j, right3, height - 1));
}
}
calcBBox(node, this.toBBox);
return node;
},
_chooseSubtree: function (bbox, node, level, path) {
var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
while (true) {
path.push(node);
if (node.leaf || path.length - 1 === level) break;
minArea = minEnlargement = Infinity;
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
area = bboxArea(child.bbox);
enlargement = enlargedArea(bbox, child.bbox) - area;
// choose entry with the least area enlargement
if (enlargement < minEnlargement) {
minEnlargement = enlargement;
minArea = area < minArea ? area : minArea;
targetNode = child;
} else if (enlargement === minEnlargement) {
// otherwise choose one with the smallest area
if (area < minArea) {
minArea = area;
targetNode = child;
}
}
}
node = targetNode;
}
return node;
},
_insert: function (item, level, isNode) {
var toBBox = this.toBBox,
bbox = isNode ? item.bbox : toBBox(item),
insertPath = [];
// find the best node for accommodating the item, saving all nodes along the path too
var node = this._chooseSubtree(bbox, this.data, level, insertPath);
// put the item into the node
node.children.push(item);
extend(node.bbox, bbox);
// split on node overflow; propagate upwards if necessary
while (level >= 0) {
if (insertPath[level].children.length > this._maxEntries) {
this._split(insertPath, level);
level--;
} else break;
}
// adjust bboxes along the insertion path
this._adjustParentBBoxes(bbox, insertPath, level);
},
// split overflowed node into two
_split: function (insertPath, level) {
var node = insertPath[level],
M = node.children.length,
m = this._minEntries;
this._chooseSplitAxis(node, m, M);
var newNode = {
children: node.children.splice(this._chooseSplitIndex(node, m, M)),
height: node.height
};
if (node.leaf) newNode.leaf = true;
calcBBox(node, this.toBBox);
calcBBox(newNode, this.toBBox);
if (level) insertPath[level - 1].children.push(newNode);
else this._splitRoot(node, newNode);
},
_splitRoot: function (node, newNode) {
// split root node
this.data = {
children: [node, newNode],
height: node.height + 1
};
calcBBox(this.data, this.toBBox);
},
_chooseSplitIndex: function (node, m, M) {
var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
minOverlap = minArea = Infinity;
for (i = m; i <= M - m; i++) {
bbox1 = distBBox(node, 0, i, this.toBBox);
bbox2 = distBBox(node, i, M, this.toBBox);
overlap = intersectionArea(bbox1, bbox2);
area = bboxArea(bbox1) + bboxArea(bbox2);
// choose distribution with minimum overlap
if (overlap < minOverlap) {
minOverlap = overlap;
index = i;
minArea = area < minArea ? area : minArea;
} else if (overlap === minOverlap) {
// otherwise choose distribution with minimum area
if (area < minArea) {
minArea = area;
index = i;
}
}
}
return index;
},
// sorts node children by the best axis for split
_chooseSplitAxis: function (node, m, M) {
var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
xMargin = this._allDistMargin(node, m, M, compareMinX),
yMargin = this._allDistMargin(node, m, M, compareMinY);
// if total distributions margin value is minimal for x, sort by minX,
// otherwise it's already sorted by minY
if (xMargin < yMargin) node.children.sort(compareMinX);
},
// total margin of all possible split distributions where each node is at least m full
_allDistMargin: function (node, m, M, compare) {
node.children.sort(compare);
var toBBox = this.toBBox,
leftBBox = distBBox(node, 0, m, toBBox),
rightBBox = distBBox(node, M - m, M, toBBox),
margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
i, child;
for (i = m; i < M - m; i++) {
child = node.children[i];
extend(leftBBox, node.leaf ? toBBox(child) : child.bbox);
margin += bboxMargin(leftBBox);
}
for (i = M - m - 1; i >= m; i--) {
child = node.children[i];
extend(rightBBox, node.leaf ? toBBox(child) : child.bbox);
margin += bboxMargin(rightBBox);
}
return margin;
},
_adjustParentBBoxes: function (bbox, path, level) {
// adjust bboxes along the given tree path
for (var i = level; i >= 0; i--) {
extend(path[i].bbox, bbox);
}
},
_condense: function (path) {
// go through the path, removing empty nodes and updating bboxes
for (var i = path.length - 1, siblings; i >= 0; i--) {
if (path[i].children.length === 0) {
if (i > 0) {
siblings = path[i - 1].children;
siblings.splice(siblings.indexOf(path[i]), 1);
} else this.clear();
} else calcBBox(path[i], this.toBBox);
}
},
_initFormat: function (format) {
// data format (minX, minY, maxX, maxY accessors)
// uses eval-type function compilation instead of just accepting a toBBox function
// because the algorithms are very sensitive to sorting functions performance,
// so they should be dead simple and without inner calls
// jshint evil: true
var compareArr = ['return a', ' - b', ';'];
this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
}
};
// calculate node's bbox from bboxes of its children
function calcBBox(node, toBBox) {
node.bbox = distBBox(node, 0, node.children.length, toBBox);
}
// min bounding rectangle of node children from k to p-1
function distBBox(node, k, p, toBBox) {
var bbox = empty();
for (var i = k, child; i < p; i++) {
child = node.children[i];
extend(bbox, node.leaf ? toBBox(child) : child.bbox);
}
return bbox;
}
function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; }
function extend(a, b) {
a[0] = Math.min(a[0], b[0]);
a[1] = Math.min(a[1], b[1]);
a[2] = Math.max(a[2], b[2]);
a[3] = Math.max(a[3], b[3]);
return a;
}
function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; }
function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; }
function bboxArea(a) { return (a[2] - a[0]) * (a[3] - a[1]); }
function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); }
function enlargedArea(a, b) {
return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
(Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
}
function intersectionArea(a, b) {
var minX = Math.max(a[0], b[0]),
minY = Math.max(a[1], b[1]),
maxX = Math.min(a[2], b[2]),
maxY = Math.min(a[3], b[3]);
return Math.max(0, maxX - minX) *
Math.max(0, maxY - minY);
}
function contains(a, b) {
return a[0] <= b[0] &&
a[1] <= b[1] &&
b[2] <= a[2] &&
b[3] <= a[3];
}
function intersects(a, b) {
return b[0] <= a[2] &&
b[1] <= a[3] &&
b[2] >= a[0] &&
b[3] >= a[1];
}
// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
// combines selection algorithm with binary divide & conquer approach
function multiSelect(arr, left, right, n, compare) {
var stack = [left, right],
mid;
while (stack.length) {
right = stack.pop();
left = stack.pop();
if (right - left <= n) continue;
mid = left + Math.ceil((right - left) / n / 2) * n;
select(arr, left, right, mid, compare);
stack.push(left, mid, mid, right);
}
}
// Floyd-Rivest selection algorithm:
// sort an array between left and right (inclusive) so that the smallest k elements come first (unordered)
function select(arr, left, right, k, compare) {
var n, i, z, s, sd, newLeft, newRight, t, j;
while (right > left) {
if (right - left > 600) {
n = right - left + 1;
i = k - left + 1;
z = Math.log(n);
s = 0.5 * Math.exp(2 * z / 3);
sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1);
newLeft = Math.max(left, Math.floor(k - i * s / n + sd));
newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd));
select(arr, newLeft, newRight, k, compare);
}
t = arr[k];
i = left;
j = right;
swap(arr, left, k);
if (compare(arr[right], t) > 0) swap(arr, left, right);
while (i < j) {
swap(arr, i, j);
i++;
j--;
while (compare(arr[i], t) < 0) i++;
while (compare(arr[j], t) > 0) j--;
}
if (compare(arr[left], t) === 0) swap(arr, left, j);
else {
j++;
swap(arr, j, right);
}
if (j <= k) left = j + 1;
if (k <= j) right = j - 1;
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// export as AMD/CommonJS module or global variable
if (typeof define === 'function' && define.amd) define('rbush', function() { return rbush; });
else if (typeof module !== 'undefined') module.exports = rbush;
else if (typeof self !== 'undefined') self.rbush = rbush;
else window.rbush = rbush;
})();
},{}],115:[function(require,module,exports){
// Copyright 2014 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
void (function(root, factory) {
if (typeof define === "function" && define.amd) {
define(factory)
} else if (typeof exports === "object") {
module.exports = factory()
} else {
root.resolveUrl = factory()
}
}(this, function() {
function resolveUrl(/* ...urls */) {
var numUrls = arguments.length
if (numUrls === 0) {
throw new Error("resolveUrl requires at least one argument; got none.")
}
var base = document.createElement("base")
base.href = arguments[0]
if (numUrls === 1) {
return base.href
}
var head = document.getElementsByTagName("head")[0]
head.insertBefore(base, head.firstChild)
var a = document.createElement("a")
var resolved
for (var index = 1; index < numUrls; index++) {
a.href = arguments[index]
resolved = a.href
base.href = resolved
}
head.removeChild(base)
return resolved
}
return resolveUrl
}));
},{}],116:[function(require,module,exports){
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Ported from Webkit
* http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h
*/
module.exports = UnitBezier;
function UnitBezier(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p2y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier.prototype.sampleCurveX = function(t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
};
UnitBezier.prototype.sampleCurveY = function(t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
};
UnitBezier.prototype.sampleCurveDerivativeX = function(t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
};
UnitBezier.prototype.solveCurveX = function(x, epsilon) {
if (typeof epsilon === 'undefined') epsilon = 1e-6;
var t0, t1, t2, x2, i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++) {
x2 = this.sampleCurveX(t2) - x;
if (Math.abs(x2) < epsilon) return t2;
var d2 = this.sampleCurveDerivativeX(t2);
if (Math.abs(d2) < 1e-6) break;
t2 = t2 - x2 / d2;
}
// Fall back to the bisection method for reliability.
t0 = 0.0;
t1 = 1.0;
t2 = x;
if (t2 < t0) return t0;
if (t2 > t1) return t1;
while (t0 < t1) {
x2 = this.sampleCurveX(t2);
if (Math.abs(x2 - x) < epsilon) return t2;
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
// Failure.
return t2;
};
UnitBezier.prototype.solve = function(x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
};
},{}],117:[function(require,module,exports){
module.exports.VectorTile = require('./lib/vectortile.js');
module.exports.VectorTileFeature = require('./lib/vectortilefeature.js');
module.exports.VectorTileLayer = require('./lib/vectortilelayer.js');
},{"./lib/vectortile.js":118,"./lib/vectortilefeature.js":119,"./lib/vectortilelayer.js":120}],118:[function(require,module,exports){
'use strict';
var VectorTileLayer = require('./vectortilelayer');
module.exports = VectorTile;
function VectorTile(pbf, end) {
this.layers = pbf.readFields(readTile, {}, end);
}
function readTile(tag, layers, pbf) {
if (tag === 3) {
var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
if (layer.length) layers[layer.name] = layer;
}
}
},{"./vectortilelayer":120}],119:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
module.exports = VectorTileFeature;
function VectorTileFeature(pbf, end, extent, keys, values) {
// Public
this.properties = {};
this.extent = extent;
this.type = 0;
// Private
this._pbf = pbf;
this._geometry = -1;
this._keys = keys;
this._values = values;
pbf.readFields(readFeature, this, end);
}
function readFeature(tag, feature, pbf) {
if (tag == 1) feature._id = pbf.readVarint();
else if (tag == 2) readTag(pbf, feature);
else if (tag == 3) feature.type = pbf.readVarint();
else if (tag == 4) feature._geometry = pbf.pos;
}
function readTag(pbf, feature) {
var end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var key = feature._keys[pbf.readVarint()],
value = feature._values[pbf.readVarint()];
feature.properties[key] = value;
}
}
VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
VectorTileFeature.prototype.loadGeometry = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
lines = [],
line;
while (pbf.pos < end) {
if (!length) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (cmd === 1) { // moveTo
if (line) lines.push(line);
line = [];
}
line.push(new Point(x, y));
} else if (cmd === 7) {
line.push(line[0].clone()); // closePolygon
} else {
throw new Error('unknown command ' + cmd);
}
}
if (line) lines.push(line);
return lines;
};
VectorTileFeature.prototype.bbox = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
x1 = Infinity,
x2 = -Infinity,
y1 = Infinity,
y2 = -Infinity;
while (pbf.pos < end) {
if (!length) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
} else if (cmd !== 7) {
throw new Error('unknown command ' + cmd);
}
}
return [x1, y1, x2, y2];
};
VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
var size = this.extent * Math.pow(2, z),
x0 = this.extent * x,
y0 = this.extent * y,
coords = this.loadGeometry(),
type = VectorTileFeature.types[this.type];
for (var i = 0; i < coords.length; i++) {
var line = coords[i];
for (var j = 0; j < line.length; j++) {
var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
line[j] = [
(p.x + x0) * 360 / size - 180,
360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90
];
}
}
if (type === 'Point' && coords.length === 1) {
coords = coords[0][0];
} else if (type === 'Point') {
coords = coords[0];
type = 'MultiPoint';
} else if (type === 'LineString' && coords.length === 1) {
coords = coords[0];
} else if (type === 'LineString') {
type = 'MultiLineString';
}
return {
type: "Feature",
geometry: {
type: type,
coordinates: coords
},
properties: this.properties
};
};
},{"point-geometry":113}],120:[function(require,module,exports){
'use strict';
var VectorTileFeature = require('./vectortilefeature.js');
module.exports = VectorTileLayer;
function VectorTileLayer(pbf, end) {
// Public
this.version = 1;
this.name = null;
this.extent = 4096;
this.length = 0;
// Private
this._pbf = pbf;
this._keys = [];
this._values = [];
this._features = [];
pbf.readFields(readLayer, this, end);
this.length = this._features.length;
}
function readLayer(tag, layer, pbf) {
if (tag === 15) layer.version = pbf.readVarint();
else if (tag === 1) layer.name = pbf.readString();
else if (tag === 5) layer.extent = pbf.readVarint();
else if (tag === 2) layer._features.push(pbf.pos);
else if (tag === 3) layer._keys.push(pbf.readString());
else if (tag === 4) layer._values.push(readValueMessage(pbf));
}
function readValueMessage(pbf) {
var value = null,
end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var tag = pbf.readVarint() >> 3;
value = tag === 1 ? pbf.readString() :
tag === 2 ? pbf.readFloat() :
tag === 3 ? pbf.readDouble() :
tag === 4 ? pbf.readVarint64() :
tag === 5 ? pbf.readVarint() :
tag === 6 ? pbf.readSVarint() :
tag === 7 ? pbf.readBoolean() : null;
}
return value;
}
// return feature `i` from this layer as a `VectorTileFeature`
VectorTileLayer.prototype.feature = function(i) {
if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
this._pbf.pos = this._features[i];
var end = this._pbf.readVarint() + this._pbf.pos;
return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
};
},{"./vectortilefeature.js":119}],121:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],122:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
currentQueue[queueIndex].run();
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],123:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],124:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":123,"_process":122,"inherits":121}],125:[function(require,module,exports){
var bundleFn = arguments[3];
var sources = arguments[4];
var cache = arguments[5];
var stringify = JSON.stringify;
module.exports = function (fn) {
var keys = [];
var wkey;
var cacheKeys = Object.keys(cache);
for (var i = 0, l = cacheKeys.length; i < l; i++) {
var key = cacheKeys[i];
if (cache[key].exports === fn) {
wkey = key;
break;
}
}
if (!wkey) {
wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
var wcache = {};
for (var i = 0, l = cacheKeys.length; i < l; i++) {
var key = cacheKeys[i];
wcache[key] = key;
}
sources[wkey] = [
Function(['require','module','exports'], '(' + fn + ')(self)'),
wcache
];
}
var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
var scache = {}; scache[wkey] = wkey;
sources[skey] = [
Function(['require'],'require(' + stringify(wkey) + ')(self)'),
scache
];
var src = '(' + bundleFn + ')({'
+ Object.keys(sources).map(function (key) {
return stringify(key) + ':['
+ sources[key][0]
+ ',' + stringify(sources[key][1]) + ']'
;
}).join(',')
+ '},{},[' + stringify(skey) + '])'
;
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
return new Worker(URL.createObjectURL(
new Blob([src], { type: 'text/javascript' })
));
};
},{}]},{},[22])(22)
});
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyX3NldC5qcyIsImpzL2RhdGEvYnVmZmVyL2NvbGxpc2lvbl9ib3hfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2ZpbGxfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2dseXBoX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9pY29uX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9saW5lX2VsZW1lbnRfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvbGluZV92ZXJ0ZXhfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvb3V0bGluZV9lbGVtZW50c19idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci90cmlhbmdsZV9lbGVtZW50X2J1ZmZlci5qcyIsImpzL2RhdGEvY3JlYXRlX2J1Y2tldC5qcyIsImpzL2RhdGEvZWxlbWVudF9ncm91cHMuanMiLCJqcy9kYXRhL2ZlYXR1cmVfdHJlZS5qcyIsImpzL2RhdGEvZmlsbF9idWNrZXQuanMiLCJqcy9kYXRhL2xpbmVfYnVja2V0LmpzIiwianMvZGF0YS9zeW1ib2xfYnVja2V0LmpzIiwianMvZ2VvL2Nvb3JkaW5hdGUuanMiLCJqcy9nZW8vbGF0X2xuZy5qcyIsImpzL2dlby9sYXRfbG5nX2JvdW5kcy5qcyIsImpzL2dlby90cmFuc2Zvcm0uanMiLCJqcy9saWIvZGVidWd0ZXh0LmpzIiwianMvbWFwYm94LWdsLmpzIiwianMvcmVuZGVyL2RyYXdfYmFja2dyb3VuZC5qcyIsImpzL3JlbmRlci9kcmF3X2NvbGxpc2lvbl9kZWJ1Zy5qcyIsImpzL3JlbmRlci9kcmF3X2RlYnVnLmpzIiwianMvcmVuZGVyL2RyYXdfZmlsbC5qcyIsImpzL3JlbmRlci9kcmF3X2xpbmUuanMiLCJqcy9yZW5kZXIvZHJhd19yYXN0ZXIuanMiLCJqcy9yZW5kZXIvZHJhd19zeW1ib2wuanMiLCJqcy9yZW5kZXIvZHJhd192ZXJ0aWNlcy5qcyIsImpzL3JlbmRlci9mcmFtZV9oaXN0b3J5LmpzIiwianMvcmVuZGVyL2dsX3V0aWwuanMiLCJqcy9yZW5kZXIvbGluZV9hdGxhcy5qcyIsImpzL3JlbmRlci9wYWludGVyLmpzIiwianMvcmVuZGVyL3NoYWRlcnMuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl9zb3VyY2UuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl93cmFwcGVyLmpzIiwianMvc291cmNlL3Jhc3Rlcl90aWxlX3NvdXJjZS5qcyIsImpzL3NvdXJjZS9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdGlsZS5qcyIsImpzL3NvdXJjZS90aWxlX2Nvb3JkLmpzIiwianMvc291cmNlL3RpbGVfcHlyYW1pZC5qcyIsImpzL3NvdXJjZS92ZWN0b3JfdGlsZV9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdmlkZW9fc291cmNlLmpzIiwianMvc291cmNlL3dvcmtlci5qcyIsImpzL3NvdXJjZS93b3JrZXJfdGlsZS5qcyIsImpzL3N0eWxlL2FuaW1hdGlvbl9sb29wLmpzIiwianMvc3R5bGUvaW1hZ2Vfc3ByaXRlLmpzIiwianMvc3R5bGUvbGF5b3V0X3Byb3BlcnRpZXMuanMiLCJqcy9zdHlsZS9wYWludF9wcm9wZXJ0aWVzLmpzIiwianMvc3R5bGUvcmVmZXJlbmNlLmpzIiwianMvc3R5bGUvc3R5bGUuanMiLCJqcy9zdHlsZS9zdHlsZV9jb25zdGFudC5qcyIsImpzL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uLmpzIiwianMvc3R5bGUvc3R5bGVfZGVjbGFyYXRpb25fc2V0LmpzIiwianMvc3R5bGUvc3R5bGVfbGF5ZXIuanMiLCJqcy9zdHlsZS9zdHlsZV90cmFuc2l0aW9uLmpzIiwianMvc3ltYm9sL2FuY2hvci5qcyIsImpzL3N5bWJvbC9iaW5fcGFjay5qcyIsImpzL3N5bWJvbC9jaGVja19tYXhfYW5nbGUuanMiLCJqcy9zeW1ib2wvY2xpcF9saW5lLmpzIiwianMvc3ltYm9sL2NvbGxpc2lvbl9ib3guanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX2ZlYXR1cmUuanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX3RpbGUuanMiLCJqcy9zeW1ib2wvZ2V0X2FuY2hvcnMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfYXRsYXMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfc291cmNlLmpzIiwianMvc3ltYm9sL21lcmdlbGluZXMuanMiLCJqcy9zeW1ib2wvcXVhZHMuanMiLCJqcy9zeW1ib2wvcmVzb2x2ZV9pY29ucy5qcyIsImpzL3N5bWJvbC9yZXNvbHZlX3RleHQuanMiLCJqcy9zeW1ib2wvc2hhcGluZy5qcyIsImpzL3N5bWJvbC9zcHJpdGVfYXRsYXMuanMiLCJqcy91aS9jYW1lcmEuanMiLCJqcy91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzIiwianMvdWkvY29udHJvbC9jb250cm9sLmpzIiwianMvdWkvY29udHJvbC9uYXZpZ2F0aW9uLmpzIiwianMvdWkvaGFuZGxlcnMuanMiLCJqcy91aS9oYXNoLmpzIiwianMvdWkvaW50ZXJhY3Rpb24uanMiLCJqcy91aS9tYXAuanMiLCJqcy91aS9wb3B1cC5qcyIsImpzL3V0aWwvYWN0b3IuanMiLCJqcy91dGlsL2Jyb3dzZXIvYWpheC5qcyIsImpzL3V0aWwvYnJvd3Nlci9icm93c2VyLmpzIiwianMvdXRpbC9icm93c2VyL2NhbnZhcy5qcyIsImpzL3V0aWwvYnJvd3Nlci9kaXNwYXRjaGVyLmpzIiwianMvdXRpbC9icm93c2VyL2RvbS5qcyIsImpzL3V0aWwvY29uZmlnLmpzIiwianMvdXRpbC9ldmVudGVkLmpzIiwianMvdXRpbC9nbHlwaHMuanMiLCJqcy91dGlsL2ludGVycG9sYXRlLmpzIiwianMvdXRpbC9tYXBib3guanMiLCJqcy91dGlsL21ydV9jYWNoZS5qcyIsImpzL3V0aWwvdG9rZW4uanMiLCJqcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvY3NzY29sb3JwYXJzZXIvY3NzY29sb3JwYXJzZXIuanMiLCJub2RlX21vZHVsZXMvZmVhdHVyZS1maWx0ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2VvanNvbi12dC9zcmMvY2xpcC5qcyIsIm5vZGVfbW9kdWxlcy9nZW9qc29uLXZ0L3NyYy9jb252ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3NpbXBsaWZ5LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3RpbGUuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0cml4L2Rpc3QvZ2wtbWF0cml4LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1mdW5jdGlvbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9saWIvdmFsaWRhdGUvbGF0ZXN0LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1zdHlsZS1zcGVjL2xpYi92YWxpZGF0ZS9wYXJzZWQuanMiLCJub2RlX21vZHVsZXMvbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9yZWZlcmVuY2UvdjcuanNvbiIsIm5vZGVfbW9kdWxlcy9wYmYvYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3BiZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYmYvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcG9pbnQtZ2VvbWV0cnkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmJ1c2gvcmJ1c2guanMiLCJub2RlX21vZHVsZXMvcmVzb2x2ZS11cmwvcmVzb2x2ZS11cmwuanMiLCJub2RlX21vZHVsZXMvdW5pdGJlemllci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZS5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZWZlYXR1cmUuanMiLCJub2RlX21vZHVsZXMvdmVjdG9yLXRpbGUvbGliL3ZlY3RvcnRpbGVsYXllci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvd2Vid29ya2lmeS9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzb0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxdUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9UQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4cElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQy9KQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzFrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIndXNlIHN0cmljdCc7XG5cbi8vIGEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIGEgc2luZ2xlIGFycmF5YnVmZmVyXG5cbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyO1xuXG5mdW5jdGlvbiBCdWZmZXIoYnVmZmVyKSB7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgdGhpcy5hcnJheSA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmRlZmF1bHRMZW5ndGgpO1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGVmYXVsdExlbmd0aDtcbiAgICAgICAgdGhpcy5zZXR1cFZpZXdzKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBvbmx5IHJlY3JlYXRlIGJ1ZmZlcnMgYWZ0ZXIgcmVjZWl2aW5nIHRoZW0gZnJvbSB3b3JrZXJzIGZvciBiaW5kaW5nIHRvIGdsLFxuICAgICAgICAvLyBzbyB3ZSBvbmx5IG5lZWQgdGhlc2UgMiBwcm9wZXJ0aWVzXG4gICAgICAgIHRoaXMuYXJyYXkgPSBidWZmZXIuYXJyYXk7XG4gICAgICAgIHRoaXMucG9zID0gYnVmZmVyLnBvcztcbiAgICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUgPSB7XG4gICAgcG9zOiAwLFxuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBpbiBvbmUgaXRlbVxuICAgIGRlZmF1bHRMZW5ndGg6IDgxOTIsIC8vIGluaXRpYWwgYnVmZmVyIHNpemVcbiAgICBhcnJheVR5cGU6ICdBUlJBWV9CVUZGRVInLCAvLyBnbCBidWZmZXIgdHlwZVxuXG4gICAgZ2V0IGluZGV4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3MgLyB0aGlzLml0ZW1TaXplO1xuICAgIH0sXG5cbiAgICBzZXR1cFZpZXdzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gc2V0IHVwIHZpZXdzIGZvciBlYWNoIHR5cGUgdG8gYWRkIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzIHRvIHRoZSBzYW1lIGJ1ZmZlclxuICAgICAgICB0aGlzLnVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLmJ5dGVzID0gbmV3IEludDhBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy51c2hvcnRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLnNob3J0cyA9IG5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgIH0sXG5cbiAgICAvLyBiaW5kcyB0aGUgYnVmZmVyIHRvIGEgd2ViZ2wgY29udGV4dFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsKSB7XG4gICAgICAgIHZhciB0eXBlID0gZ2xbdGhpcy5hcnJheVR5cGVdO1xuICAgICAgICBpZiAoIXRoaXMuYnVmZmVyKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wuYmluZEJ1ZmZlcih0eXBlLCB0aGlzLmJ1ZmZlcik7XG4gICAgICAgICAgICBnbC5idWZmZXJEYXRhKHR5cGUsIHRoaXMuYXJyYXkuc2xpY2UoMCwgdGhpcy5wb3MpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgICAgIC8vIGR1bXAgYXJyYXkgYnVmZmVyIG9uY2UgaXQncyBib3VuZCB0byBnbFxuICAgICAgICAgICAgdGhpcy5hcnJheSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC5iaW5kQnVmZmVyKHR5cGUsIHRoaXMuYnVmZmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBkZXN0cm95OiBmdW5jdGlvbihnbCkge1xuICAgICAgICBpZiAodGhpcy5idWZmZXIpIHtcbiAgICAgICAgICAgIGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gaW5jcmVhc2UgdGhlIGJ1ZmZlciBzaXplIGJ5IDUwJSBpZiBhIG5ldyBpdGVtIGRvZXNuJ3QgZml0XG4gICAgcmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoIDwgdGhpcy5wb3MgKyB0aGlzLml0ZW1TaXplKSB7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmxlbmd0aCA8IHRoaXMucG9zICsgdGhpcy5pdGVtU2l6ZSkge1xuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBsZW5ndGggYnkgNTAlIGJ1dCBrZWVwIGl0IGV2ZW5cbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IE1hdGgucm91bmQodGhpcy5sZW5ndGggKiAxLjUgLyAyKSAqIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGFycmF5IGJ1ZmZlcnMgY2FuJ3QgYmUgcmVzaXplZCwgc28gd2UgY3JlYXRlIGEgbmV3IG9uZSBhbmQgcmVzZXQgYWxsIGJ5dGVzIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5QnVmZmVyKHRoaXMubGVuZ3RoKTtcblxuICAgICAgICAgICAgdmFyIHVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICAgICAgdWJ5dGVzLnNldCh0aGlzLnVieXRlcyk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExpbmVWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2xpbmVfdmVydGV4X2J1ZmZlcicpO1xudmFyIExpbmVFbGVtZW50QnVmZmVyID0gcmVxdWlyZSgnLi9saW5lX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgRmlsbFZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vZmlsbF92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgRmlsbEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgT3V0bGluZUVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL291dGxpbmVfZWxlbWVudHNfYnVmZmVyJyk7XG52YXIgR2x5cGhWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2dseXBoX3ZlcnRleF9idWZmZXInKTtcbnZhciBHbHlwaEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgSWNvblZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vaWNvbl92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgSWNvbkVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9jb2xsaXNpb25fYm94X3ZlcnRleF9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihidWZmZXJzZXQpIHtcbiAgICBidWZmZXJzZXQgPSBidWZmZXJzZXQgfHwge307XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2x5cGhWZXJ0ZXg6IG5ldyBHbHlwaFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZ2x5cGhWZXJ0ZXgpLFxuICAgICAgICBnbHlwaEVsZW1lbnQ6IG5ldyBHbHlwaEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb25WZXJ0ZXg6IG5ldyBJY29uVmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5pY29uVmVydGV4KSxcbiAgICAgICAgaWNvbkVsZW1lbnQ6IG5ldyBJY29uRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQuaWNvbkVsZW1lbnQpLFxuICAgICAgICBmaWxsVmVydGV4OiBuZXcgRmlsbFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZmlsbFZlcnRleCksXG4gICAgICAgIGZpbGxFbGVtZW50OiBuZXcgRmlsbEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmZpbGxFbGVtZW50KSxcbiAgICAgICAgb3V0bGluZUVsZW1lbnQ6IG5ldyBPdXRsaW5lRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQub3V0bGluZUVsZW1lbnQpLFxuICAgICAgICBsaW5lVmVydGV4OiBuZXcgTGluZVZlcnRleEJ1ZmZlcihidWZmZXJzZXQubGluZVZlcnRleCksXG4gICAgICAgIGxpbmVFbGVtZW50OiBuZXcgTGluZUVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmxpbmVFbGVtZW50KSxcbiAgICAgICAgY29sbGlzaW9uQm94VmVydGV4OiBuZXcgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5jb2xsaXNpb25Cb3hWZXJ0ZXgpXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5Db2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiAxMiwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIGFkZDogZnVuY3Rpb24ocG9pbnQsIGV4dHJ1ZGUsIG1heFpvb20sIHBsYWNlbWVudFpvb20pIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXg7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSBwb2ludC54O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSBwb2ludC55O1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQoZXh0cnVkZS54KTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChleHRydWRlLnkpO1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSA9IE1hdGguZmxvb3IobWF4Wm9vbSAqIDEwKTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gPSBNYXRoLmZsb29yKHBsYWNlbWVudFpvb20gKiAxMCk7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gRmlsbFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogNCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ID09IDQgYnl0ZXMpXG5cbiAgICBhZGQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSB4O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSB5O1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgZGVmYXVsdExlbmd0aDogMjA0OCAqIDE2LFxuICAgIGl0ZW1TaXplOiAxNixcblxuICAgIGFkZDogZnVuY3Rpb24oeCwgeSwgb3gsIG95LCB0eCwgdHksIG1pbnpvb20sIG1heHpvb20sIGxhYmVsbWluem9vbSkge1xuICAgICAgICB2YXIgcG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICBwb3MyID0gcG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IHg7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAxXSA9IHk7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQob3ggKiA2NCk7IC8vIHVzZSAxLzY0IHBpeGVscyBmb3IgcGxhY2VtZW50XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAzXSA9IE1hdGgucm91bmQob3kgKiA2NCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMVxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSAvKiB0ZXggKi8gPSBNYXRoLmZsb29yKHR4IC8gNCk7XG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDldIC8qIHRleCAqLyA9IE1hdGguZmxvb3IodHkgLyA0KTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTBdIC8qIGxhYmVsbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKGxhYmVsbWluem9vbSkgKiAxMCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMl0gLyogbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKG1pbnpvb20pICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcblxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGExLCA0LCBnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA4KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMiwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgMTIpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2x5cGhWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIEdseXBoVmVydGV4QnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBkZWZhdWx0TGVuZ3RoOiAyMDQ4ICogMTYsXG4gICAgaXRlbVNpemU6IDE2LFxuXG4gICAgYWRkOiBmdW5jdGlvbih4LCB5LCBveCwgb3ksIHR4LCB0eSwgbWluem9vbSwgbWF4em9vbSwgbGFiZWxtaW56b29tKSB7XG4gICAgICAgIHZhciBwb3MgPSB0aGlzLnBvcyxcbiAgICAgICAgICAgIHBvczIgPSBwb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDBdID0geDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0geTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDJdID0gTWF0aC5yb3VuZChveCAqIDY0KTsgLy8gdXNlIDEvNjQgcGl4ZWxzIGZvciBwbGFjZW1lbnRcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChveSAqIDY0KTtcblxuICAgICAgICAvLyBhX2RhdGExXG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDhdIC8qIHRleCAqLyA9IHR4IC8gNDtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gLyogdGV4ICovID0gdHkgLyA0O1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMF0gLyogbGFiZWxtaW56b29tICovID0gTWF0aC5mbG9vcigobGFiZWxtaW56b29tIHx8IDApICogMTApO1xuXG4gICAgICAgIC8vIGFfZGF0YTJcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTJdIC8qIG1pbnpvb20gKi8gPSBNYXRoLmZsb29yKChtaW56b29tIHx8IDApICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSB8fCAyNSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMSwgNCwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgOCk7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YTIsIDIsIGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlLCBzdHJpZGUsIG9mZnNldCArIDEyKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVFbGVtZW50QnVmZmVyO1xuXG5mdW5jdGlvbiBMaW5lRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgaXRlbVNpemU6IDYsIC8vIGJ5dGVzIHBlciB0cmlhbmdsZSAoMyAqIHVuc2lnbmVkIHNob3J0ID09IDYgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDJdID0gYztcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZVZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gTGluZVZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG4vLyBzY2FsZSB0aGUgZXh0cnVzaW9uIHZlY3RvciBzbyB0aGF0IHRoZSBub3JtYWwgbGVuZ3RoIGlzIHRoaXMgdmFsdWUuXG4vLyBjb250YWlucyB0aGUgXCJ0ZXh0dXJlXCIgbm9ybWFscyAoLTEuLjEpLiB0aGlzIGlzIGRpc3RpbmN0IGZyb20gdGhlIGV4dHJ1ZGVcbi8vIG5vcm1hbHMgZm9yIGxpbmUgam9pbnMsIGJlY2F1c2UgdGhlIHgtdmFsdWUgcmVtYWlucyAwIGZvciB0aGUgdGV4dHVyZVxuLy8gbm9ybWFsIGFycmF5LCB3aGlsZSB0aGUgZXh0cnVkZSBub3JtYWwgYWN0dWFsbHkgbW92ZXMgdGhlIHZlcnRleCB0byBjcmVhdGVcbi8vIHRoZSBhY3V0ZS9iZXZlbGxlZCBsaW5lIGpvaW4uXG5MaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZSA9IDYzO1xuXG5MaW5lVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogOCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIC8vIHR4LCB0eSAtIHRleHR1cmUgbm9ybWFsXG4gICAgYWRkOiBmdW5jdGlvbihwb2ludCwgZXh0cnVkZSwgdHgsIHR5LCBsaW5lc29mYXIpIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXgsXG4gICAgICAgICAgICBleHRydWRlU2NhbGUgPSBMaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZTtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IChNYXRoLmZsb29yKHBvaW50LngpICogMikgfCB0eDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0gKE1hdGguZmxvb3IocG9pbnQueSkgKiAyKSB8IHR5O1xuXG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNF0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueCk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNV0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueSk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNl0gPSAobGluZXNvZmFyIHx8IDApIC8gMTI4O1xuICAgICAgICB0aGlzLmJ5dGVzW3BvcyArIDddID0gKGxpbmVzb2ZhciB8fCAwKSAlIDEyODtcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBPdXRsaW5lRWxlbWVudHNCdWZmZXI7XG5cbmZ1bmN0aW9uIE91dGxpbmVFbGVtZW50c0J1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5PdXRsaW5lRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBwZXIgbGluZSAoMiAqIHVuc2lnbmVkIHNob3J0ID09IDQgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyO1xuXG5mdW5jdGlvbiBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cblRyaWFuZ2xlRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA2LCAvLyBieXRlcyBwZXIgdHJpYW5nbGUgKDMgKiB1bnNpZ25lZCBzaG9ydCA9PSA2IGJ5dGVzKVxuICAgIGFycmF5VHlwZTogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcblxuICAgIGFkZDogZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAgICB2YXIgcG9zMiA9IHRoaXMucG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDFdID0gYjtcbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAyXSA9IGM7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCdWNrZXQ7XG5cbnZhciBMaW5lQnVja2V0ID0gcmVxdWlyZSgnLi9saW5lX2J1Y2tldCcpO1xudmFyIEZpbGxCdWNrZXQgPSByZXF1aXJlKCcuL2ZpbGxfYnVja2V0Jyk7XG52YXIgU3ltYm9sQnVja2V0ID0gcmVxdWlyZSgnLi9zeW1ib2xfYnVja2V0Jyk7XG52YXIgTGF5b3V0UHJvcGVydGllcyA9IHJlcXVpcmUoJy4uL3N0eWxlL2xheW91dF9wcm9wZXJ0aWVzJyk7XG52YXIgZmVhdHVyZUZpbHRlciA9IHJlcXVpcmUoJ2ZlYXR1cmUtZmlsdGVyJyk7XG52YXIgU3R5bGVEZWNsYXJhdGlvblNldCA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uX3NldCcpO1xuXG5mdW5jdGlvbiBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgeiwgb3ZlcnNjYWxpbmcsIGNvbGxpc2lvbkRlYnVnKSB7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBTdHlsZURlY2xhcmF0aW9uU2V0KCdsYXlvdXQnLCBsYXllci50eXBlLCBsYXllci5sYXlvdXQsIHt9KS52YWx1ZXMoKSxcbiAgICAgICAgZmFrZVpvb21IaXN0b3J5ID0geyBsYXN0SW50ZWdlclpvb206IEluZmluaXR5LCBsYXN0SW50ZWdlclpvb21UaW1lOiAwLCBsYXN0Wm9vbTogMCB9LFxuICAgICAgICBsYXlvdXQgPSB7fTtcblxuICAgIGZvciAodmFyIGsgaW4gdmFsdWVzKSB7XG4gICAgICAgIGxheW91dFtrXSA9IHZhbHVlc1trXS5jYWxjdWxhdGUoeiwgZmFrZVpvb21IaXN0b3J5KTtcbiAgICB9XG5cbiAgICB2YXIgQnVja2V0Q2xhc3MgPVxuICAgICAgICBsYXllci50eXBlID09PSAnbGluZScgPyBMaW5lQnVja2V0IDpcbiAgICAgICAgbGF5ZXIudHlwZSA9PT0gJ2ZpbGwnID8gRmlsbEJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdzeW1ib2wnID8gU3ltYm9sQnVja2V0IDogbnVsbDtcblxuICAgIHZhciBidWNrZXQgPSBuZXcgQnVja2V0Q2xhc3MoYnVmZmVycywgbmV3IExheW91dFByb3BlcnRpZXNbbGF5ZXIudHlwZV0obGF5b3V0KSwgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpO1xuXG4gICAgYnVja2V0LmlkID0gbGF5ZXIuaWQ7XG4gICAgYnVja2V0LnR5cGUgPSBsYXllci50eXBlO1xuICAgIGJ1Y2tldFsnc291cmNlLWxheWVyJ10gPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgYnVja2V0LmludGVyYWN0aXZlID0gbGF5ZXIuaW50ZXJhY3RpdmU7XG4gICAgYnVja2V0Lm1pblpvb20gPSBsYXllci5taW56b29tO1xuICAgIGJ1Y2tldC5tYXhab29tID0gbGF5ZXIubWF4em9vbTtcbiAgICBidWNrZXQuZmlsdGVyID0gZmVhdHVyZUZpbHRlcihsYXllci5maWx0ZXIpO1xuICAgIGJ1Y2tldC5mZWF0dXJlcyA9IFtdO1xuXG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBFbGVtZW50R3JvdXBzO1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXBzKHZlcnRleEJ1ZmZlciwgZWxlbWVudEJ1ZmZlciwgc2Vjb25kRWxlbWVudEJ1ZmZlcikge1xuXG4gICAgdGhpcy52ZXJ0ZXhCdWZmZXIgPSB2ZXJ0ZXhCdWZmZXI7XG4gICAgdGhpcy5lbGVtZW50QnVmZmVyID0gZWxlbWVudEJ1ZmZlcjtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRCdWZmZXIgPSBzZWNvbmRFbGVtZW50QnVmZmVyO1xuICAgIHRoaXMuZ3JvdXBzID0gW107XG59XG5cbkVsZW1lbnRHcm91cHMucHJvdG90eXBlLm1ha2VSb29tRm9yID0gZnVuY3Rpb24obnVtVmVydGljZXMpIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudCB8fCB0aGlzLmN1cnJlbnQudmVydGV4TGVuZ3RoICsgbnVtVmVydGljZXMgPiA2NTUzNSkge1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuZXcgRWxlbWVudEdyb3VwKHRoaXMudmVydGV4QnVmZmVyLmluZGV4LFxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudEJ1ZmZlciAmJiB0aGlzLmVsZW1lbnRCdWZmZXIuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRFbGVtZW50QnVmZmVyICYmIHRoaXMuc2Vjb25kRWxlbWVudEJ1ZmZlci5pbmRleCk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXAodmVydGV4U3RhcnRJbmRleCwgZWxlbWVudFN0YXJ0SW5kZXgsIHNlY29uZEVsZW1lbnRTdGFydEluZGV4KSB7XG4gICAgLy8gdGhlIG9mZnNldCBpbnRvIHRoZSB2ZXJ0ZXggYnVmZmVyIG9mIHRoZSBmaXJzdCB2ZXJ0ZXggaW4gdGhpcyBncm91cFxuICAgIHRoaXMudmVydGV4U3RhcnRJbmRleCA9IHZlcnRleFN0YXJ0SW5kZXg7XG4gICAgdGhpcy5lbGVtZW50U3RhcnRJbmRleCA9IGVsZW1lbnRTdGFydEluZGV4O1xuICAgIHRoaXMuc2Vjb25kRWxlbWVudFN0YXJ0SW5kZXggPSBzZWNvbmRFbGVtZW50U3RhcnRJbmRleDtcbiAgICB0aGlzLmVsZW1lbnRMZW5ndGggPSAwO1xuICAgIHRoaXMudmVydGV4TGVuZ3RoID0gMDtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRMZW5ndGggPSAwO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmJ1c2ggPSByZXF1aXJlKCdyYnVzaCcpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciB2dCA9IHJlcXVpcmUoJ3ZlY3Rvci10aWxlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZlYXR1cmVUcmVlO1xuXG5mdW5jdGlvbiBGZWF0dXJlVHJlZShjb29yZCwgb3ZlcnNjYWxpbmcpIHtcbiAgICB0aGlzLnggPSBjb29yZC54O1xuICAgIHRoaXMueSA9IGNvb3JkLnk7XG4gICAgdGhpcy56ID0gY29vcmQueiAtIE1hdGgubG9nKG92ZXJzY2FsaW5nKSAvIE1hdGguTE4yO1xuICAgIHRoaXMucnRyZWUgPSByYnVzaCg5KTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufVxuXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24oYmJveCwgbGF5ZXJzLCBmZWF0dXJlKSB7XG4gICAgYmJveC5sYXllcnMgPSBsYXllcnM7XG4gICAgYmJveC5mZWF0dXJlID0gZmVhdHVyZTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZC5wdXNoKGJib3gpO1xufTtcblxuLy8gYnVsayBpbnNlcnQgaW50byB0cmVlXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuX2xvYWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnJ0cmVlLmxvYWQodGhpcy50b0JlSW5zZXJ0ZWQpO1xuICAgIHRoaXMudG9CZUluc2VydGVkID0gW107XG59O1xuXG4vLyBGaW5kcyBmZWF0dXJlcyBpbiB0aGlzIHRpbGUgYXQgYSBwYXJ0aWN1bGFyIHBvc2l0aW9uLlxuRmVhdHVyZVRyZWUucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24oYXJncywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy50b0JlSW5zZXJ0ZWQubGVuZ3RoKSB0aGlzLl9sb2FkKCk7XG5cbiAgICB2YXIgcGFyYW1zID0gYXJncy5wYXJhbXMgfHwge30sXG4gICAgICAgIHJhZGl1cyA9IChwYXJhbXMucmFkaXVzIHx8IDApICogNDA5NiAvIGFyZ3Muc2NhbGUsXG4gICAgICAgIHggPSBhcmdzLngsXG4gICAgICAgIHkgPSBhcmdzLnksXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgdmFyIG1hdGNoaW5nID0gdGhpcy5ydHJlZS5zZWFyY2goWyB4IC0gcmFkaXVzLCB5IC0gcmFkaXVzLCB4ICsgcmFkaXVzLCB5ICsgcmFkaXVzIF0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBtYXRjaGluZ1tpXS5mZWF0dXJlLFxuICAgICAgICAgICAgbGF5ZXJzID0gbWF0Y2hpbmdbaV0ubGF5ZXJzLFxuICAgICAgICAgICAgdHlwZSA9IHZ0LlZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW2ZlYXR1cmUudHlwZV07XG5cbiAgICAgICAgaWYgKHBhcmFtcy4kdHlwZSAmJiB0eXBlICE9PSBwYXJhbXMuJHR5cGUpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgaWYgKCFnZW9tZXRyeUNvbnRhaW5zUG9pbnQoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSwgdHlwZSwgbmV3IFBvaW50KHgsIHkpLCByYWRpdXMpKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIGdlb0pTT04gPSBmZWF0dXJlLnRvR2VvSlNPTih0aGlzLngsIHRoaXMueSwgdGhpcy56KTtcbiAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCBsYXllcnMubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IGxheWVyc1tsXTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5sYXllciAmJiBsYXllciAhPT0gcGFyYW1zLmxheWVyLmlkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICByZXN1bHQucHVzaCh1dGlsLmV4dGVuZCh7bGF5ZXI6IGxheWVyfSwgZ2VvSlNPTikpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0KTtcbn07XG5cbmZ1bmN0aW9uIGdlb21ldHJ5Q29udGFpbnNQb2ludChyaW5ncywgdHlwZSwgcCwgcmFkaXVzKSB7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdQb2ludCcgPyBwb2ludENvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cykgOlxuICAgICAgICAgICB0eXBlID09PSAnTGluZVN0cmluZycgPyBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6XG4gICAgICAgICAgIHR5cGUgPT09ICdQb2x5Z29uJyA/IHBvbHlDb250YWluc1BvaW50KHJpbmdzLCBwKSB8fCBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6IGZhbHNlO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTUwMTcyNS8zMzEzNzkuXG5mdW5jdGlvbiBkaXN0VG9TZWdtZW50U3F1YXJlZChwLCB2LCB3KSB7XG4gICAgdmFyIGwyID0gdi5kaXN0U3FyKHcpO1xuICAgIGlmIChsMiA9PT0gMCkgcmV0dXJuIHAuZGlzdFNxcih2KTtcbiAgICB2YXIgdCA9ICgocC54IC0gdi54KSAqICh3LnggLSB2LngpICsgKHAueSAtIHYueSkgKiAody55IC0gdi55KSkgLyBsMjtcbiAgICBpZiAodCA8IDApIHJldHVybiBwLmRpc3RTcXIodik7XG4gICAgaWYgKHQgPiAxKSByZXR1cm4gcC5kaXN0U3FyKHcpO1xuICAgIHJldHVybiBwLmRpc3RTcXIody5zdWIodikuX211bHQodCkuX2FkZCh2KSk7XG59XG5cbmZ1bmN0aW9uIGxpbmVDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAvLyBGaW5kIGxpbmUgc2VnbWVudHMgdGhhdCBoYXZlIGEgZGlzdGFuY2UgPD0gcmFkaXVzXjIgdG8gcFxuICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlLCB3ZSB0cmVhdCB0aGUgbGluZSBhcyBcImNvbnRhaW5pbmcgcG9pbnQgcFwiLlxuICAgICAgICAgICAgdmFyIHYgPSByaW5nW2ogLSAxXSwgdyA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoZGlzdFRvU2VnbWVudFNxdWFyZWQocCwgdiwgdykgPCByKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIHBvaW50IGluIHBvbHlnb24gcmF5IGNhc3RpbmcgYWxnb3JpdGhtXG5mdW5jdGlvbiBwb2x5Q29udGFpbnNQb2ludChyaW5ncywgcCkge1xuICAgIHZhciBjID0gZmFsc2UsXG4gICAgICAgIHJpbmcsIHAxLCBwMjtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgcmluZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgcmluZyA9IHJpbmdzW2tdO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHJpbmcubGVuZ3RoIC0gMTsgaSA8IHJpbmcubGVuZ3RoOyBqID0gaSsrKSB7XG4gICAgICAgICAgICBwMSA9IHJpbmdbaV07XG4gICAgICAgICAgICBwMiA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoKChwMS55ID4gcC55KSAhPT0gKHAyLnkgPiBwLnkpKSAmJiAocC54IDwgKHAyLnggLSBwMS54KSAqIChwLnkgLSBwMS55KSAvIChwMi55IC0gcDEueSkgKyBwMS54KSkge1xuICAgICAgICAgICAgICAgIGMgPSAhYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gcG9pbnRDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAocmluZ1tqXS5kaXN0U3FyKHApIDw9IHIpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbEJ1Y2tldDtcblxuZnVuY3Rpb24gRmlsbEJ1Y2tldChidWZmZXJzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmZpbGxWZXJ0ZXgsIGJ1ZmZlcnMuZmlsbEVsZW1lbnQsIGJ1ZmZlcnMub3V0bGluZUVsZW1lbnQpO1xufVxuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmZWF0dXJlcyA9IHRoaXMuZmVhdHVyZXM7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xuICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxufTtcblxuRmlsbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmFkZEZpbGwobGluZXNbaV0pO1xuICAgIH1cbn07XG5cbkZpbGxCdWNrZXQucHJvdG90eXBlLmFkZEZpbGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIGlmICh2ZXJ0aWNlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgIC8vY29uc29sZS53YXJuKCdhIGZpbGwgbXVzdCBoYXZlIGF0IGxlYXN0IHRocmVlIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiB2ZXJ0aWNlcyB3ZSdyZSBnb2luZyB0byBwcm9kdWNlIHNvIHRoYXQgd2VcbiAgICAvLyBjYW4gcmVzaXplIHRoZSBidWZmZXIgYmVmb3JlaGFuZCwgb3IgZGV0ZWN0IHdoZXRoZXIgdGhlIGN1cnJlbnQgbGluZVxuICAgIC8vIHdvbid0IGZpdCBpbnRvIHRoZSBidWZmZXIgYW55bW9yZS5cbiAgICAvLyBJbiBvcmRlciB0byBiZSBhYmxlIHRvIHVzZSB0aGUgdmVydGV4IGJ1ZmZlciBmb3IgZHJhd2luZyB0aGUgYW50aWFsaWFzZWRcbiAgICAvLyBvdXRsaW5lcywgd2Ugc2VwYXJhdGUgYWxsIHBvbHlnb24gdmVydGljZXMgd2l0aCBhIGRlZ2VuZXJhdGUgKG91dC1vZi1cbiAgICAvLyB2aWV3cGxhbmUpIHZlcnRleC5cblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG5cbiAgICAvLyBDaGVjayB3aGV0aGVyIHRoaXMgZ2VvbWV0cnkgYnVmZmVyIGNhbiBob2xkIGFsbCB0aGUgcmVxdWlyZWQgdmVydGljZXMuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLm1ha2VSb29tRm9yKGxlbiArIDEpO1xuICAgIHZhciBlbGVtZW50R3JvdXAgPSB0aGlzLmVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciBmaWxsVmVydGV4ID0gdGhpcy5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmFyIGZpbGxFbGVtZW50ID0gdGhpcy5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIHZhciBvdXRsaW5lRWxlbWVudCA9IHRoaXMuYnVmZmVycy5vdXRsaW5lRWxlbWVudDtcblxuICAgIC8vIFdlJ3JlIGdlbmVyYXRpbmcgdHJpYW5nbGUgZmFucywgc28gd2UgYWx3YXlzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IGNvb3JkaW5hdGUgaW4gdGhpcyBwb2x5Z29uLlxuICAgIHZhciBmaXJzdEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4LFxuICAgICAgICBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCwgY3VycmVudFZlcnRleDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4O1xuICAgICAgICBjdXJyZW50VmVydGV4ID0gdmVydGljZXNbaV07XG5cbiAgICAgICAgZmlsbFZlcnRleC5hZGQoY3VycmVudFZlcnRleC54LCBjdXJyZW50VmVydGV4LnkpO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoKys7XG5cbiAgICAgICAgLy8gT25seSBhZGQgdHJpYW5nbGVzIHRoYXQgaGF2ZSBkaXN0aW5jdCB2ZXJ0aWNlcy5cbiAgICAgICAgaWYgKGkgPj0gMiAmJiAoY3VycmVudFZlcnRleC54ICE9PSB2ZXJ0aWNlc1swXS54IHx8IGN1cnJlbnRWZXJ0ZXgueSAhPT0gdmVydGljZXNbMF0ueSkpIHtcbiAgICAgICAgICAgIGZpbGxFbGVtZW50LmFkZChmaXJzdEluZGV4LCBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCk7XG4gICAgICAgICAgICBlbGVtZW50R3JvdXAuZWxlbWVudExlbmd0aCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGkgPj0gMSkge1xuICAgICAgICAgICAgb3V0bGluZUVsZW1lbnQuYWRkKHByZXZJbmRleCwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cC5zZWNvbmRFbGVtZW50TGVuZ3RoKys7XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2SW5kZXggPSBjdXJyZW50SW5kZXg7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZUJ1Y2tldDtcblxuZnVuY3Rpb24gTGluZUJ1Y2tldChidWZmZXJzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmxpbmVWZXJ0ZXgsIGJ1ZmZlcnMubGluZUVsZW1lbnQpO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG59XG5cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaV07XG4gICAgICAgIHRoaXMuYWRkRmVhdHVyZShmZWF0dXJlLmxvYWRHZW9tZXRyeSgpKTtcbiAgICB9XG59O1xuXG5MaW5lQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlID0gZnVuY3Rpb24obGluZXMpIHtcbiAgICB2YXIgbGF5b3V0UHJvcGVydGllcyA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuYWRkTGluZShsaW5lc1tpXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtam9pbiddLFxuICAgICAgICAgICAgbGF5b3V0UHJvcGVydGllc1snbGluZS1jYXAnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtbWl0ZXItbGltaXQnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtcm91bmQtbGltaXQnXSk7XG4gICAgfVxufTtcblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkTGluZSA9IGZ1bmN0aW9uKHZlcnRpY2VzLCBqb2luLCBjYXAsIG1pdGVyTGltaXQsIHJvdW5kTGltaXQpIHtcblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG4gICAgLy8gSWYgdGhlIGxpbmUgaGFzIGR1cGxpY2F0ZSB2ZXJ0aWNlcyBhdCB0aGUgZW5kLCBhZGp1c3QgbGVuZ3RoIHRvIHJlbW92ZSB0aGVtLlxuICAgIHdoaWxlIChsZW4gPiAyICYmIHZlcnRpY2VzW2xlbiAtIDFdLmVxdWFscyh2ZXJ0aWNlc1tsZW4gLSAyXSkpIHtcbiAgICAgICAgbGVuLS07XG4gICAgfVxuXG4gICAgaWYgKHZlcnRpY2VzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgLy9jb25zb2xlLndhcm4oJ2EgbGluZSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoam9pbiA9PT0gJ2JldmVsJykgbWl0ZXJMaW1pdCA9IDEuMDU7XG5cbiAgICB2YXIgZmlyc3RWZXJ0ZXggPSB2ZXJ0aWNlc1swXSxcbiAgICAgICAgbGFzdFZlcnRleCA9IHZlcnRpY2VzW2xlbiAtIDFdLFxuICAgICAgICBjbG9zZWQgPSBmaXJzdFZlcnRleC5lcXVhbHMobGFzdFZlcnRleCk7XG5cbiAgICAvLyB3ZSBjb3VsZCBiZSBtb3JlIHByZWNpc2UsIGJ1dCBpdCB3b3VsZCBvbmx5IHNhdmUgYSBuZWdsaWdpYmxlIGFtb3VudCBvZiBzcGFjZVxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKiA0KTtcblxuICAgIGlmIChsZW4gPT09IDIgJiYgY2xvc2VkKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignYSBsaW5lIG1heSBub3QgaGF2ZSBjb2luY2lkZW50IHBvaW50cycpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGJlZ2luQ2FwID0gY2FwLFxuICAgICAgICBlbmRDYXAgPSBjbG9zZWQgPyAnYnV0dCcgOiBjYXAsXG4gICAgICAgIGZsaXAgPSAxLFxuICAgICAgICBkaXN0YW5jZSA9IDAsXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gdHJ1ZSxcbiAgICAgICAgY3VycmVudFZlcnRleCwgcHJldlZlcnRleCwgbmV4dFZlcnRleCwgcHJldk5vcm1hbCwgbmV4dE5vcm1hbCwgb2Zmc2V0QSwgb2Zmc2V0QjtcblxuICAgIC8vIHRoZSBsYXN0IHRocmVlIHZlcnRpY2VzIGFkZGVkXG4gICAgdGhpcy5lMSA9IHRoaXMuZTIgPSB0aGlzLmUzID0gLTE7XG5cbiAgICBpZiAoY2xvc2VkKSB7XG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tsZW4gLSAyXTtcbiAgICAgICAgbmV4dE5vcm1hbCA9IGZpcnN0VmVydGV4LnN1YihjdXJyZW50VmVydGV4KS5fdW5pdCgpLl9wZXJwKCk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgIG5leHRWZXJ0ZXggPSBjbG9zZWQgJiYgaSA9PT0gbGVuIC0gMSA/XG4gICAgICAgICAgICB2ZXJ0aWNlc1sxXSA6IC8vIGlmIHRoZSBsaW5lIGlzIGNsb3NlZCwgd2UgdHJlYXQgdGhlIGxhc3QgdmVydGV4IGxpa2UgdGhlIGZpcnN0XG4gICAgICAgICAgICB2ZXJ0aWNlc1tpICsgMV07IC8vIGp1c3QgdGhlIG5leHQgdmVydGV4XG5cbiAgICAgICAgLy8gaWYgdHdvIGNvbnNlY3V0aXZlIHZlcnRpY2VzIGV4aXN0LCBza2lwIHRoZSBjdXJyZW50IG9uZVxuICAgICAgICBpZiAobmV4dFZlcnRleCAmJiB2ZXJ0aWNlc1tpXS5lcXVhbHMobmV4dFZlcnRleCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChuZXh0Tm9ybWFsKSBwcmV2Tm9ybWFsID0gbmV4dE5vcm1hbDtcbiAgICAgICAgaWYgKGN1cnJlbnRWZXJ0ZXgpIHByZXZWZXJ0ZXggPSBjdXJyZW50VmVydGV4O1xuXG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tpXTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgaG93IGZhciBhbG9uZyB0aGUgbGluZSB0aGUgY3VycmVudFZlcnRleCBpc1xuICAgICAgICBpZiAocHJldlZlcnRleCkgZGlzdGFuY2UgKz0gY3VycmVudFZlcnRleC5kaXN0KHByZXZWZXJ0ZXgpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbm9ybWFsIHRvd2FyZHMgdGhlIG5leHQgdmVydGV4IGluIHRoaXMgbGluZS4gSW4gY2FzZVxuICAgICAgICAvLyB0aGVyZSBpcyBubyBuZXh0IHZlcnRleCwgcHJldGVuZCB0aGF0IHRoZSBsaW5lIGlzIGNvbnRpbnVpbmcgc3RyYWlnaHQsXG4gICAgICAgIC8vIG1lYW5pbmcgdGhhdCB3ZSBhcmUganVzdCB1c2luZyB0aGUgcHJldmlvdXMgbm9ybWFsLlxuICAgICAgICBuZXh0Tm9ybWFsID0gbmV4dFZlcnRleCA/IG5leHRWZXJ0ZXguc3ViKGN1cnJlbnRWZXJ0ZXgpLl91bml0KCkuX3BlcnAoKSA6IHByZXZOb3JtYWw7XG5cbiAgICAgICAgLy8gSWYgd2Ugc3RpbGwgZG9uJ3QgaGF2ZSBhIHByZXZpb3VzIG5vcm1hbCwgdGhpcyBpcyB0aGUgYmVnaW5uaW5nIG9mIGFcbiAgICAgICAgLy8gbm9uLWNsb3NlZCBsaW5lLCBzbyB3ZSdyZSBkb2luZyBhIHN0cmFpZ2h0IFwiam9pblwiLlxuICAgICAgICBwcmV2Tm9ybWFsID0gcHJldk5vcm1hbCB8fCBuZXh0Tm9ybWFsO1xuXG4gICAgICAgIC8vIERldGVybWluZSB0aGUgbm9ybWFsIG9mIHRoZSBqb2luIGV4dHJ1c2lvbi4gSXQgaXMgdGhlIGFuZ2xlIGJpc2VjdG9yXG4gICAgICAgIC8vIG9mIHRoZSBzZWdtZW50cyBiZXR3ZWVuIHRoZSBwcmV2aW91cyBsaW5lIGFuZCB0aGUgbmV4dCBsaW5lLlxuICAgICAgICB2YXIgam9pbk5vcm1hbCA9IHByZXZOb3JtYWwuYWRkKG5leHROb3JtYWwpLl91bml0KCk7XG5cbiAgICAgICAgLyogIGpvaW5Ob3JtYWwgICAgIHByZXZOb3JtYWxcbiAgICAgICAgICogICAgICAgICAgICAg4oaWICAgICAg4oaRXG4gICAgICAgICAqICAgICAgICAgICAgICAgIC5fX19fX19fXy4gcHJldlZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqIG5leHROb3JtYWwgIOKGkCAgfCAgY3VycmVudFZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqICAgICBuZXh0VmVydGV4ICFcbiAgICAgICAgICpcbiAgICAgICAgICovXG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBsZW5ndGggb2YgdGhlIG1pdGVyICh0aGUgcmF0aW8gb2YgdGhlIG1pdGVyIHRvIHRoZSB3aWR0aCkuXG4gICAgICAgIC8vIEZpbmQgdGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgbmV4dCBhbmQgam9pbiBub3JtYWxzXG4gICAgICAgIC8vIHVzaW5nIGRvdCBwcm9kdWN0LiBUaGUgaW52ZXJzZSBvZiB0aGF0IGlzIHRoZSBtaXRlciBsZW5ndGguXG4gICAgICAgIHZhciBjb3NIYWxmQW5nbGUgPSBqb2luTm9ybWFsLnggKiBuZXh0Tm9ybWFsLnggKyBqb2luTm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnk7XG4gICAgICAgIHZhciBtaXRlckxlbmd0aCA9IDEgLyBjb3NIYWxmQW5nbGU7XG5cbiAgICAgICAgLy8gVGhlIGpvaW4gaWYgYSBtaWRkbGUgdmVydGV4LCBvdGhlcndpc2UgdGhlIGNhcC5cbiAgICAgICAgdmFyIG1pZGRsZVZlcnRleCA9IHByZXZWZXJ0ZXggJiYgbmV4dFZlcnRleDtcbiAgICAgICAgdmFyIGN1cnJlbnRKb2luID0gbWlkZGxlVmVydGV4ID8gam9pbiA6IG5leHRWZXJ0ZXggPyBiZWdpbkNhcCA6IGVuZENhcDtcblxuICAgICAgICBpZiAobWlkZGxlVmVydGV4ICYmIGN1cnJlbnRKb2luID09PSAncm91bmQnICYmIG1pdGVyTGVuZ3RoIDwgcm91bmRMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInICYmIG1pdGVyTGVuZ3RoID4gbWl0ZXJMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnYmV2ZWwnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBUaGUgbWF4aW11bSBleHRydWRlIGxlbmd0aCBpcyAxMjggLyA2MyA9IDIgdGltZXMgdGhlIHdpZHRoIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICAvLyBzbyBpZiBtaXRlckxlbmd0aCA+PSAyIHdlIG5lZWQgdG8gZHJhdyBhIGRpZmZlcmVudCB0eXBlIG9mIGJldmVsIHdoZXJlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoID4gMikgY3VycmVudEpvaW4gPSAnZmxpcGJldmVsJztcblxuICAgICAgICAgICAgLy8gSWYgdGhlIG1pdGVyTGVuZ3RoIGlzIHJlYWxseSBzbWFsbCBhbmQgdGhlIGxpbmUgYmV2ZWwgd291bGRuJ3QgYmUgdmlzaWJsZSxcbiAgICAgICAgICAgIC8vIGp1c3QgZHJhdyBhIG1pdGVyIGpvaW4gdG8gc2F2ZSBhIHRyaWFuZ2xlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoIDwgbWl0ZXJMaW1pdCkgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInKSB7XG4gICAgICAgICAgICBqb2luTm9ybWFsLl9tdWx0KG1pdGVyTGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgam9pbk5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdmbGlwYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBtaXRlciBpcyB0b28gYmlnLCBmbGlwIHRoZSBkaXJlY3Rpb24gdG8gbWFrZSBhIGJldmVsZWQgam9pblxuXG4gICAgICAgICAgICBpZiAobWl0ZXJMZW5ndGggPiAxMDApIHtcbiAgICAgICAgICAgICAgICAvLyBBbG1vc3QgcGFyYWxsZWwgbGluZXNcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsID0gbmV4dE5vcm1hbC5jbG9uZSgpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBwcmV2Tm9ybWFsLnggKiBuZXh0Tm9ybWFsLnkgLSBwcmV2Tm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnggPiAwID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgIHZhciBiZXZlbExlbmd0aCA9IG1pdGVyTGVuZ3RoICogcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkubWFnKCkgLyBwcmV2Tm9ybWFsLnN1YihuZXh0Tm9ybWFsKS5tYWcoKTtcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsLl9wZXJwKCkuX211bHQoYmV2ZWxMZW5ndGggKiBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBqb2luTm9ybWFsLCAwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICBmbGlwID0gLWZsaXA7XG5cbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Sm9pbiA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgdmFyIGRpciA9IHByZXZOb3JtYWwueCAqIG5leHROb3JtYWwueSAtIHByZXZOb3JtYWwueSAqIG5leHROb3JtYWwueDtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAtTWF0aC5zcXJ0KG1pdGVyTGVuZ3RoICogbWl0ZXJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGlmIChmbGlwICogZGlyID4gMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJldmVsXG4gICAgICAgICAgICBpZiAoIXN0YXJ0T2ZMaW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCBvZmZzZXRBLCBvZmZzZXRCLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC1vZmZzZXRBLCAtb2Zmc2V0QiwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdidXR0Jykge1xuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJ1dHRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIHByZXZOb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RhcnQgbmV4dCBzZWdtZW50IHdpdGggYSBidXR0XG4gICAgICAgICAgICBpZiAobmV4dFZlcnRleCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbmV4dE5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdzcXVhcmUnKSB7XG5cbiAgICAgICAgICAgIGlmICghc3RhcnRPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAvLyBDbG9zZSBwcmV2aW91cyBzZWdtZW50IHdpdGggYSBzcXVhcmUgY2FwXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgc2VnbWVudCBpcyBkb25lLiBVbnNldCB2ZXJ0aWNlcyB0byBkaXNjb25uZWN0IHNlZ21lbnRzLlxuICAgICAgICAgICAgICAgIHRoaXMuZTEgPSB0aGlzLmUyID0gLTE7XG4gICAgICAgICAgICAgICAgZmxpcCA9IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdyb3VuZCcpIHtcblxuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBidXR0XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAwLCAwLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgcm91bmQgY2FwIG9yIGxpbmVqb2luIGF0IGVuZCBvZiBzZWdtZW50XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSBzZWdtZW50IGlzIGRvbmUuIFVuc2V0IHZlcnRpY2VzIHRvIGRpc2Nvbm5lY3Qgc2VnbWVudHMuXG4gICAgICAgICAgICAgICAgdGhpcy5lMSA9IHRoaXMuZTIgPSAtMTtcbiAgICAgICAgICAgICAgICBmbGlwID0gMTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChiZWdpbkNhcCA9PT0gJ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIC8vIEFkZCByb3VuZCBjYXAgYmVmb3JlIGZpcnN0IHNlZ21lbnRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudCB3aXRoIGEgYnV0dFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gZmFsc2U7XG4gICAgfVxuXG5cbn07XG5cbi8qKlxuICogQWRkIHR3byB2ZXJ0aWNlcyB0byB0aGUgYnVmZmVycy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3VycmVudFZlcnRleCB0aGUgbGluZSB2ZXJ0ZXggdG8gYWRkIGJ1ZmZlciB2ZXJ0aWNlcyBmb3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBmbGlwIC0xIGlmIHRoZSB2ZXJ0aWNlcyBzaG91bGQgYmUgZmxpcHBlZCwgMSBvdGhlcndpc2VcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZSB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgYmVnZ2luaW5nIG9mIHRoZSBsaW5lIHRvIHRoZSB2ZXJ0ZXhcbiAqIEBwYXJhbSB7TnVtYmVyfSBlbmRMZWZ0IGV4dHJ1ZGUgdG8gc2hpZnQgdGhlIGxlZnQgdmVydGV4IGFsb25nIHRoZSBsaW5lXG4gKiBAcGFyYW0ge051bWJlcn0gZW5kUmlnaHQgZXh0cnVkZSB0byBzaGlmdCB0aGUgbGVmdCB2ZXJ0ZXggYWxvbmcgdGhlIGxpbmVcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gcm91bmQgd2hldGhlciB0aGlzIGlzIGEgcm91bmQgY2FwXG4gKi9cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEN1cnJlbnRWZXJ0ZXggPSBmdW5jdGlvbihjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbm9ybWFsLCBlbmRMZWZ0LCBlbmRSaWdodCwgcm91bmQpIHtcbiAgICB2YXIgdHggPSByb3VuZCA/IDEgOiAwO1xuICAgIHZhciBleHRydWRlO1xuXG4gICAgdmFyIGxpbmVWZXJ0ZXggPSB0aGlzLmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2YXIgbGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMubGluZUVsZW1lbnQ7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IHRoaXMuZWxlbWVudEdyb3Vwcy5jdXJyZW50O1xuICAgIHZhciB2ZXJ0ZXhTdGFydEluZGV4ID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQudmVydGV4U3RhcnRJbmRleDtcblxuICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdChmbGlwKTtcbiAgICBpZiAoZW5kTGVmdCkgZXh0cnVkZS5fc3ViKG5vcm1hbC5wZXJwKCkuX211bHQoZW5kTGVmdCkpO1xuICAgIHRoaXMuZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMCwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICBpZiAodGhpcy5lMSA+PSAwICYmIHRoaXMuZTIgPj0gMCkge1xuICAgICAgICBsaW5lRWxlbWVudC5hZGQodGhpcy5lMSwgdGhpcy5lMiwgdGhpcy5lMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoKys7XG4gICAgfVxuICAgIHRoaXMuZTEgPSB0aGlzLmUyO1xuICAgIHRoaXMuZTIgPSB0aGlzLmUzO1xuXG4gICAgZXh0cnVkZSA9IG5vcm1hbC5tdWx0KC1mbGlwKTtcbiAgICBpZiAoZW5kUmlnaHQpIGV4dHJ1ZGUuX3N1Yihub3JtYWwucGVycCgpLl9tdWx0KGVuZFJpZ2h0KSk7XG4gICAgdGhpcy5lMyA9IGxpbmVWZXJ0ZXguYWRkKGN1cnJlbnRWZXJ0ZXgsIGV4dHJ1ZGUsIHR4LCAxLCBkaXN0YW5jZSkgLSB2ZXJ0ZXhTdGFydEluZGV4O1xuICAgIGlmICh0aGlzLmUxID49IDAgJiYgdGhpcy5lMiA+PSAwKSB7XG4gICAgICAgIGxpbmVFbGVtZW50LmFkZCh0aGlzLmUxLCB0aGlzLmUyLCB0aGlzLmUzKTtcbiAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICB9XG4gICAgdGhpcy5lMSA9IHRoaXMuZTI7XG4gICAgdGhpcy5lMiA9IHRoaXMuZTM7XG5cbiAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudF9ncm91cHMnKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG52YXIgZ2V0QW5jaG9ycyA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nZXRfYW5jaG9ycycpO1xudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG52YXIgUXVhZHMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcXVhZHMnKTtcbnZhciBTaGFwaW5nID0gcmVxdWlyZSgnLi4vc3ltYm9sL3NoYXBpbmcnKTtcbnZhciByZXNvbHZlVGV4dCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9yZXNvbHZlX3RleHQnKTtcbnZhciByZXNvbHZlSWNvbnMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcmVzb2x2ZV9pY29ucycpO1xudmFyIG1lcmdlTGluZXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvbWVyZ2VsaW5lcycpO1xudmFyIHNoYXBlVGV4dCA9IFNoYXBpbmcuc2hhcGVUZXh0O1xudmFyIHNoYXBlSWNvbiA9IFNoYXBpbmcuc2hhcGVJY29uO1xudmFyIGdldEdseXBoUXVhZHMgPSBRdWFkcy5nZXRHbHlwaFF1YWRzO1xudmFyIGdldEljb25RdWFkcyA9IFF1YWRzLmdldEljb25RdWFkcztcbnZhciBjbGlwTGluZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9jbGlwX2xpbmUnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbnZhciBDb2xsaXNpb25GZWF0dXJlID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl9mZWF0dXJlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU3ltYm9sQnVja2V0O1xuXG5mdW5jdGlvbiBTeW1ib2xCdWNrZXQoYnVmZmVycywgbGF5b3V0UHJvcGVydGllcywgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpIHtcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG4gICAgdGhpcy5jb2xsaXNpb24gPSBjb2xsaXNpb247XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IG92ZXJzY2FsaW5nO1xuICAgIHRoaXMuY29sbGlzaW9uRGVidWcgPSBjb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3ltYm9sSW5zdGFuY2VzID0gW107XG5cbn1cblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gdGhpcy50ZXh0RmVhdHVyZXM7XG5cbiAgICB2YXIgaG9yaXpvbnRhbEFsaWduID0gMC41LFxuICAgICAgICB2ZXJ0aWNhbEFsaWduID0gMC41O1xuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBjYXNlICd0b3AtcmlnaHQnOlxuICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgICAgaG9yaXpvbnRhbEFsaWduID0gMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICBjYXNlICdib3R0b20tbGVmdCc6XG4gICAgICAgICAgICBob3Jpem9udGFsQWxpZ24gPSAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgY2FzZSAnYm90dG9tLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgY2FzZSAndG9wLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDA7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIganVzdGlmeSA9IGxheW91dFsndGV4dC1qdXN0aWZ5J10gPT09ICdyaWdodCcgPyAxIDpcbiAgICAgICAgbGF5b3V0Wyd0ZXh0LWp1c3RpZnknXSA9PT0gJ2xlZnQnID8gMCA6XG4gICAgICAgIDAuNTtcblxuICAgIHZhciBvbmVFbSA9IDI0O1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gbGF5b3V0Wyd0ZXh0LWxpbmUtaGVpZ2h0J10gKiBvbmVFbTtcbiAgICB2YXIgbWF4V2lkdGggPSBsYXlvdXRbJ3N5bWJvbC1wbGFjZW1lbnQnXSAhPT0gJ2xpbmUnID8gbGF5b3V0Wyd0ZXh0LW1heC13aWR0aCddICogb25lRW0gOiAwO1xuICAgIHZhciBzcGFjaW5nID0gbGF5b3V0Wyd0ZXh0LWxldHRlci1zcGFjaW5nJ10gKiBvbmVFbTtcbiAgICB2YXIgdGV4dE9mZnNldCA9IFtsYXlvdXRbJ3RleHQtb2Zmc2V0J11bMF0gKiBvbmVFbSwgbGF5b3V0Wyd0ZXh0LW9mZnNldCddWzFdICogb25lRW1dO1xuICAgIHZhciBmb250c3RhY2sgPSBsYXlvdXRbJ3RleHQtZm9udCddO1xuXG4gICAgdmFyIGdlb21ldHJpZXMgPSBbXTtcbiAgICBmb3IgKHZhciBnID0gMDsgZyA8IGZlYXR1cmVzLmxlbmd0aDsgZysrKSB7XG4gICAgICAgIGdlb21ldHJpZXMucHVzaChmZWF0dXJlc1tnXS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgLy8gTWVyZ2UgYWRqYWNlbnQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IHRvIGltcHJvdmUgbGFiZWxsaW5nLlxuICAgICAgICAvLyBJdCdzIGJldHRlciB0byBwbGFjZSBsYWJlbHMgb24gb25lIGxvbmcgbGluZSB0aGFuIG9uIG1hbnkgc2hvcnQgc2VnbWVudHMuXG4gICAgICAgIHZhciBtZXJnZWQgPSBtZXJnZUxpbmVzKGZlYXR1cmVzLCB0ZXh0RmVhdHVyZXMsIGdlb21ldHJpZXMpO1xuXG4gICAgICAgIGdlb21ldHJpZXMgPSBtZXJnZWQuZ2VvbWV0cmllcztcbiAgICAgICAgZmVhdHVyZXMgPSBtZXJnZWQuZmVhdHVyZXM7XG4gICAgICAgIHRleHRGZWF0dXJlcyA9IG1lcmdlZC50ZXh0RmVhdHVyZXM7XG4gICAgfVxuXG4gICAgdmFyIHNoYXBlZFRleHQsIHNoYXBlZEljb247XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGlmICghZ2VvbWV0cmllc1trXSkgY29udGludWU7XG5cbiAgICAgICAgaWYgKHRleHRGZWF0dXJlc1trXSkge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IHNoYXBlVGV4dCh0ZXh0RmVhdHVyZXNba10sIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10sIG1heFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBsaW5lSGVpZ2h0LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIGp1c3RpZnksIHNwYWNpbmcsIHRleHRPZmZzZXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5b3V0WydpY29uLWltYWdlJ10pIHtcbiAgICAgICAgICAgIHZhciBpY29uTmFtZSA9IHJlc29sdmVUb2tlbnMoZmVhdHVyZXNba10ucHJvcGVydGllcywgbGF5b3V0WydpY29uLWltYWdlJ10pO1xuICAgICAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pY29uc1tpY29uTmFtZV07XG4gICAgICAgICAgICBzaGFwZWRJY29uID0gc2hhcGVJY29uKGltYWdlLCBsYXlvdXQpO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZGZJY29ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2RmSWNvbnMgPSBpbWFnZS5zZGY7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNkZkljb25zICE9PSBpbWFnZS5zZGYpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdTdHlsZSBzaGVldCB3YXJuaW5nOiBDYW5ub3QgbWl4IFNERiBhbmQgbm9uLVNERiBpY29ucyBpbiBvbmUgYnVja2V0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkSWNvbiA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hhcGVkVGV4dCB8fCBzaGFwZWRJY29uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZ2VvbWV0cmllc1trXSwgc2hhcGVkVGV4dCwgc2hhcGVkSWNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnBsYWNlRmVhdHVyZXModGhpcy5idWZmZXJzLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICB2YXIgZ2x5cGhTaXplID0gMjQ7XG5cbiAgICB2YXIgZm9udFNjYWxlID0gbGF5b3V0Wyd0ZXh0LW1heC1zaXplJ10gLyBnbHlwaFNpemUsXG4gICAgICAgIHRleHRCb3hTY2FsZSA9IGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyAqIGZvbnRTY2FsZSxcbiAgICAgICAgaWNvbkJveFNjYWxlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydpY29uLW1heC1zaXplJ10sXG4gICAgICAgIHN5bWJvbE1pbkRpc3RhbmNlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydzeW1ib2wtbWluLWRpc3RhbmNlJ10sXG4gICAgICAgIGF2b2lkRWRnZXMgPSBsYXlvdXRbJ3N5bWJvbC1hdm9pZC1lZGdlcyddLFxuICAgICAgICB0ZXh0UGFkZGluZyA9IGxheW91dFsndGV4dC1wYWRkaW5nJ10gKiBjb2xsaXNpb24udGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIGljb25QYWRkaW5nID0gbGF5b3V0WydpY29uLXBhZGRpbmcnXSAqIGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdGV4dE1heEFuZ2xlID0gbGF5b3V0Wyd0ZXh0LW1heC1hbmdsZSddIC8gMTgwICogTWF0aC5QSSxcbiAgICAgICAgdGV4dEFsb25nTGluZSA9IGxheW91dFsndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgaWNvbkFsb25nTGluZSA9IGxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICAgICAgbGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddO1xuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgbGluZXMgPSBjbGlwTGluZShsaW5lcywgMCwgMCwgNDA5NiwgNDA5Nik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYW5jaG9yIHBvaW50cyBhcm91bmQgd2hpY2ggeW91IHdhbnQgdG8gcGxhY2UgbGFiZWxzXG4gICAgICAgIHZhciBhbmNob3JzID0gbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyA/XG4gICAgICAgICAgICBnZXRBbmNob3JzKGxpbmUsIHN5bWJvbE1pbkRpc3RhbmNlLCB0ZXh0TWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgdGV4dEJveFNjYWxlLCB0aGlzLm92ZXJzY2FsaW5nKSA6XG4gICAgICAgICAgICBbIG5ldyBBbmNob3IobGluZVswXS54LCBsaW5lWzBdLnksIDApIF07XG5cbiAgICAgICAgLy8gRm9yIGVhY2ggcG90ZW50aWFsIGxhYmVsLCBjcmVhdGUgdGhlIHBsYWNlbWVudCBmZWF0dXJlcyB1c2VkIHRvIGNoZWNrIGZvciBjb2xsaXNpb25zLCBhbmQgdGhlIHF1YWRzIHVzZSBmb3IgcmVuZGVyaW5nLlxuICAgICAgICBmb3IgKHZhciBqID0gMCwgbGVuID0gYW5jaG9ycy5sZW5ndGg7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgdmFyIGFuY2hvciA9IGFuY2hvcnNbal07XG5cbiAgICAgICAgICAgIHZhciBpbnNpZGUgPSAhKGFuY2hvci54IDwgMCB8fCBhbmNob3IueCA+IDQwOTYgfHwgYW5jaG9yLnkgPCAwIHx8IGFuY2hvci55ID4gNDA5Nik7XG5cbiAgICAgICAgICAgIGlmIChhdm9pZEVkZ2VzICYmICFpbnNpZGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBOb3JtYWxseSBzeW1ib2wgbGF5ZXJzIGFyZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBPbmx5IHN5bWJvbHNcbiAgICAgICAgICAgIC8vIHdpdGggdGhlaXIgYW5jaG9ycyB3aXRoaW4gdGhlIHRpbGUgYm91bmRhcmllcyBhcmUgYWRkZWQgdG8gdGhlIGJ1ZmZlcnNcbiAgICAgICAgICAgIC8vIHRvIHByZXZlbnQgc3ltYm9scyBmcm9tIGJlaW5nIGRyYXduIHR3aWNlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFN5bWJvbHMgaW4gbGF5ZXJzIHdpdGggb3ZlcmxhcCBhcmUgc29ydGVkIGluIHRoZSB5IGRpcmVjdGlvbiBzbyB0aGF0XG4gICAgICAgICAgICAvLyBzeW1ib2xzIGxvd2VyIG9uIHRoZSBjYW52YXMgYXJlIGRyYXduIG9uIHRvcCBvZiBzeW1ib2xzIG5lYXIgdGhlIHRvcC5cbiAgICAgICAgICAgIC8vIFRvIHByZXNlcnZlIHRoaXMgb3JkZXIgYWNyb3NzIHRpbGUgYm91bmRhcmllcyB0aGVzZSBzeW1ib2xzIGNhbid0XG4gICAgICAgICAgICAvLyBiZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBJbnN0ZWFkIHRoZXkgbmVlZCB0byBiZSBpbmNsdWRlZCBpblxuICAgICAgICAgICAgLy8gdGhlIGJ1ZmZlcnMgZm9yIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgdG8gdGlsZSBib3VuZGFyaWVzIGF0IGRyYXcgdGltZS5cbiAgICAgICAgICAgIHZhciBhZGRUb0J1ZmZlcnMgPSBpbnNpZGUgfHwgbWF5T3ZlcmxhcDtcblxuICAgICAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMucHVzaChuZXcgU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLnBsYWNlRmVhdHVyZXMgPSBmdW5jdGlvbihidWZmZXJzLCBjb2xsaXNpb25EZWJ1Zykge1xuXG4gICAgLy8gQ2FsY3VsYXRlIHdoaWNoIGxhYmVscyBjYW4gYmUgc2hvd24gYW5kIHdoZW4gdGhleSBjYW4gYmUgc2hvd24gYW5kXG4gICAgLy8gY3JlYXRlIHRoZSBidWZlcnMgdXNlZCBmb3IgcmVuZGVyaW5nLlxuXG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcblxuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGhpcy5lbGVtZW50R3JvdXBzID0ge1xuICAgICAgICB0ZXh0OiBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmdseXBoVmVydGV4LCBidWZmZXJzLmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb246IG5ldyBFbGVtZW50R3JvdXBzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCksXG4gICAgICAgIHNkZkljb25zOiB0aGlzLnNkZkljb25zXG4gICAgfTtcblxuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGNvbGxpc2lvbiA9IHRoaXMuY29sbGlzaW9uO1xuICAgIHZhciBtYXhTY2FsZSA9IHRoaXMuY29sbGlzaW9uLm1heFNjYWxlO1xuXG4gICAgdmFyIHRleHRBbG9uZ0xpbmUgPSBsYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG4gICAgdmFyIGljb25BbG9uZ0xpbmUgPSBsYXlvdXRbJ2ljb24tcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG5cbiAgICB2YXIgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICBsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddIHx8IGxheW91dFsnaWNvbi1pZ25vcmUtcGxhY2VtZW50J107XG5cbiAgICAvLyBTb3J0IHN5bWJvbHMgYnkgdGhlaXIgeSBwb3NpdGlvbiBvbiB0aGUgY2FudmFzIHNvIHRoYXQgdGhleSBsb3dlciBzeW1ib2xzXG4gICAgLy8gYXJlIGRyYXduIG9uIHRvcCBvZiBoaWdoZXIgc3ltYm9scy5cbiAgICAvLyBEb24ndCBzb3J0IHN5bWJvbHMgdGhhdCB3b24ndCBvdmVybGFwIGJlY2F1c2UgaXQgaXNuJ3QgbmVjZXNzYXJ5IGFuZFxuICAgIC8vIGJlY2F1c2UgaXQgY2F1c2VzIG1vcmUgbGFiZWxzIHRvIHBvcCBpbiBhbmQgb3V0IHdoZW4gcm90YXRpbmcuXG4gICAgaWYgKG1heU92ZXJsYXApIHtcbiAgICAgICAgdmFyIGFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGU7XG4gICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICBjb3MgPSBNYXRoLmNvcyhhbmdsZSk7XG5cbiAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICB2YXIgYVJvdGF0ZWQgPSBzaW4gKiBhLnggKyBjb3MgKiBhLnk7XG4gICAgICAgICAgICB2YXIgYlJvdGF0ZWQgPSBzaW4gKiBiLnggKyBjb3MgKiBiLnk7XG4gICAgICAgICAgICByZXR1cm4gYlJvdGF0ZWQgLSBhUm90YXRlZDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgcCA9IDA7IHAgPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IHArKykge1xuICAgICAgICB2YXIgc3ltYm9sSW5zdGFuY2UgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1twXTtcbiAgICAgICAgdmFyIGhhc1RleHQgPSBzeW1ib2xJbnN0YW5jZS5oYXNUZXh0O1xuICAgICAgICB2YXIgaGFzSWNvbiA9IHN5bWJvbEluc3RhbmNlLmhhc0ljb247XG5cbiAgICAgICAgdmFyIGljb25XaXRob3V0VGV4dCA9IGxheW91dFsndGV4dC1vcHRpb25hbCddIHx8ICFoYXNUZXh0LFxuICAgICAgICAgICAgdGV4dFdpdGhvdXRJY29uID0gbGF5b3V0WydpY29uLW9wdGlvbmFsJ10gfHwgIWhhc0ljb247XG5cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNjYWxlcyBhdCB3aGljaCB0aGUgdGV4dCBhbmQgaWNvbiBjYW4gYmUgcGxhY2VkIHdpdGhvdXQgY29sbGlzaW9uLlxuXG4gICAgICAgIHZhciBnbHlwaFNjYWxlID0gaGFzVGV4dCAmJiAhbGF5b3V0Wyd0ZXh0LWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLnRleHRDb2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuICAgICAgICB2YXIgaWNvblNjYWxlID0gaGFzSWNvbiAmJiAhbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLmljb25Db2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuXG4gICAgICAgIC8vIENvbWJpbmUgdGhlIHNjYWxlcyBmb3IgaWNvbnMgYW5kIHRleHQuXG5cbiAgICAgICAgaWYgKCFpY29uV2l0aG91dFRleHQgJiYgIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gZ2x5cGhTY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRleHRXaXRob3V0SWNvbiAmJiBnbHlwaFNjYWxlKSB7XG4gICAgICAgICAgICBnbHlwaFNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfSBlbHNlIGlmICghaWNvbldpdGhvdXRUZXh0ICYmIGljb25TY2FsZSkge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgLy8gSW5zZXJ0IGZpbmFsIHBsYWNlbWVudCBpbnRvIGNvbGxpc2lvbiB0cmVlIGFuZCBhZGQgZ2x5cGhzL2ljb25zIHRvIGJ1ZmZlcnNcblxuICAgICAgICBpZiAoaGFzVGV4dCkge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UudGV4dENvbGxpc2lvbkZlYXR1cmUsIGdseXBoU2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdseXBoU2NhbGUgPD0gbWF4U2NhbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFN5bWJvbHMoYnVmZmVycy5nbHlwaFZlcnRleCwgYnVmZmVycy5nbHlwaEVsZW1lbnQsIGVsZW1lbnRHcm91cHMudGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJvbEluc3RhbmNlLmdseXBoUXVhZHMsIGdseXBoU2NhbGUsIGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXSwgdGV4dEFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzSWNvbikge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UuaWNvbkNvbGxpc2lvbkZlYXR1cmUsIGljb25TY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaWNvblNjYWxlIDw9IG1heFNjYWxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTeW1ib2xzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCwgZWxlbWVudEdyb3Vwcy5pY29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3ltYm9sSW5zdGFuY2UuaWNvblF1YWRzLCBpY29uU2NhbGUsIGxheW91dFsnaWNvbi1rZWVwLXVwcmlnaHQnXSwgaWNvbkFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGlmIChjb2xsaXNpb25EZWJ1ZykgdGhpcy5hZGRUb0RlYnVnQnVmZmVycygpO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRTeW1ib2xzID0gZnVuY3Rpb24odmVydGV4LCBlbGVtZW50LCBlbGVtZW50R3JvdXBzLCBxdWFkcywgc2NhbGUsIGtlZXBVcHJpZ2h0LCBhbG9uZ0xpbmUpIHtcblxuICAgIGVsZW1lbnRHcm91cHMubWFrZVJvb21Gb3IoNCAqIHF1YWRzLmxlbmd0aCk7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IGVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciB6b29tID0gdGhpcy5jb2xsaXNpb24uem9vbTtcbiAgICB2YXIgcGxhY2VtZW50Wm9vbSA9IE1hdGgubWF4KE1hdGgubG9nKHNjYWxlKSAvIE1hdGguTE4yICsgem9vbSwgMCk7XG4gICAgdmFyIHBsYWNlbWVudEFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGUgKyBNYXRoLlBJO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBxdWFkcy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBxdWFkc1trXSxcbiAgICAgICAgICAgIGFuZ2xlID0gc3ltYm9sLmFuZ2xlO1xuXG4gICAgICAgIC8vIGRyb3AgdXBzaWRlIGRvd24gdmVyc2lvbnMgb2YgZ2x5cGhzXG4gICAgICAgIHZhciBhID0gKGFuZ2xlICsgcGxhY2VtZW50QW5nbGUpICUgKE1hdGguUEkgKiAyKTtcbiAgICAgICAgaWYgKGtlZXBVcHJpZ2h0ICYmIGFsb25nTGluZSAmJiAoYSA8PSBNYXRoLlBJIC8gMiB8fCBhID4gTWF0aC5QSSAqIDMgLyAyKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIHRsID0gc3ltYm9sLnRsLFxuICAgICAgICAgICAgdHIgPSBzeW1ib2wudHIsXG4gICAgICAgICAgICBibCA9IHN5bWJvbC5ibCxcbiAgICAgICAgICAgIGJyID0gc3ltYm9sLmJyLFxuICAgICAgICAgICAgdGV4ID0gc3ltYm9sLnRleCxcbiAgICAgICAgICAgIGFuY2hvciA9IHN5bWJvbC5hbmNob3IsXG5cbiAgICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heCh6b29tICsgTWF0aC5sb2coc3ltYm9sLm1pblNjYWxlKSAvIE1hdGguTE4yLCBwbGFjZW1lbnRab29tKSxcbiAgICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbih6b29tICsgTWF0aC5sb2coc3ltYm9sLm1heFNjYWxlKSAvIE1hdGguTE4yLCAyNSk7XG5cbiAgICAgICAgaWYgKG1heFpvb20gPD0gbWluWm9vbSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTG93ZXIgbWluIHpvb20gc28gdGhhdCB3aGlsZSBmYWRpbmcgb3V0IHRoZSBsYWJlbCBpdCBjYW4gYmUgc2hvd24gb3V0c2lkZSBvZiBjb2xsaXNpb24tZnJlZSB6b29tIGxldmVsc1xuICAgICAgICBpZiAobWluWm9vbSA9PT0gcGxhY2VtZW50Wm9vbSkgbWluWm9vbSA9IDA7XG5cbiAgICAgICAgdmFyIHRyaWFuZ2xlSW5kZXggPSB2ZXJ0ZXguaW5kZXggLSBlbGVtZW50R3JvdXAudmVydGV4U3RhcnRJbmRleDtcblxuICAgICAgICB2ZXJ0ZXguYWRkKGFuY2hvci54LCBhbmNob3IueSwgdGwueCwgdGwueSwgdGV4LngsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRyLngsIHRyLnksIHRleC54ICsgdGV4LncsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJsLngsIGJsLnksIHRleC54LCB0ZXgueSArIHRleC5oLCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJyLngsIGJyLnksIHRleC54ICsgdGV4LncsIHRleC55ICsgdGV4LmgsIG1pblpvb20sIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDQ7XG5cbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCwgdHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyKTtcbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyLCB0cmlhbmdsZUluZGV4ICsgMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoICs9IDI7XG4gICAgfVxuXG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmaXJzdGRvbmUgPSBmYWxzZTtcbiAgICB0aGlzLmdldFRleHREZXBlbmRlbmNpZXModGlsZSwgYWN0b3IsIGRvbmUpO1xuICAgIHRoaXMuZ2V0SWNvbkRlcGVuZGVuY2llcyh0aWxlLCBhY3RvciwgZG9uZSk7XG4gICAgZnVuY3Rpb24gZG9uZShlcnIpIHtcbiAgICAgICAgaWYgKGVyciB8fCBmaXJzdGRvbmUpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICBmaXJzdGRvbmUgPSB0cnVlO1xuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuZ2V0SWNvbkRlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmxheW91dFByb3BlcnRpZXNbJ2ljb24taW1hZ2UnXSkge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgICAgICB2YXIgaWNvbnMgPSByZXNvbHZlSWNvbnMoZmVhdHVyZXMsIHRoaXMubGF5b3V0UHJvcGVydGllcyk7XG5cbiAgICAgICAgaWYgKGljb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgYWN0b3Iuc2VuZCgnZ2V0IGljb25zJywgeyBpY29uczogaWNvbnMgfSwgc2V0SWNvbnMuYmluZCh0aGlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRJY29ucyhlcnIsIG5ld2ljb25zKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB0aGlzLmljb25zID0gbmV3aWNvbnM7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5nZXRUZXh0RGVwZW5kZW5jaWVzID0gZnVuY3Rpb24odGlsZSwgYWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgZm9udHN0YWNrID0gdGhpcy5sYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZvbnQnXTtcblxuICAgIHZhciBzdGFja3MgPSB0aGlzLnN0YWNrcyA9IHRpbGUuc3RhY2tzO1xuICAgIGlmIChzdGFja3NbZm9udHN0YWNrXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN0YWNrc1tmb250c3RhY2tdID0ge307XG4gICAgfVxuICAgIHZhciBzdGFjayA9IHN0YWNrc1tmb250c3RhY2tdO1xuXG4gICAgdmFyIGRhdGEgPSByZXNvbHZlVGV4dChmZWF0dXJlcywgdGhpcy5sYXlvdXRQcm9wZXJ0aWVzLCBzdGFjayk7XG4gICAgdGhpcy50ZXh0RmVhdHVyZXMgPSBkYXRhLnRleHRGZWF0dXJlcztcblxuICAgIGFjdG9yLnNlbmQoJ2dldCBnbHlwaHMnLCB7XG4gICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgIGZvbnRzdGFjazogZm9udHN0YWNrLFxuICAgICAgICBjb2RlcG9pbnRzOiBkYXRhLmNvZGVwb2ludHNcbiAgICB9LCBmdW5jdGlvbihlcnIsIG5ld3N0YWNrKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgIGZvciAodmFyIGNvZGVwb2ludCBpbiBuZXdzdGFjaykge1xuICAgICAgICAgICAgc3RhY2tbY29kZXBvaW50XSA9IG5ld3N0YWNrW2NvZGVwb2ludF07XG4gICAgICAgIH1cblxuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRUb0RlYnVnQnVmZmVycyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveCA9IG5ldyBFbGVtZW50R3JvdXBzKHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXgpO1xuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5jb2xsaXNpb25Cb3gubWFrZVJvb21Gb3IoMCk7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIGFuZ2xlID0gLXRoaXMuY29sbGlzaW9uLmFuZ2xlO1xuICAgIHZhciB5U3RyZXRjaCA9IHRoaXMuY29sbGlzaW9uLnlTdHJldGNoO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZlYXR1cmUgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1tqXVtpID09PSAwID8gJ3RleHRDb2xsaXNpb25GZWF0dXJlJyA6ICdpY29uQ29sbGlzaW9uRmVhdHVyZSddO1xuICAgICAgICAgICAgaWYgKCFmZWF0dXJlKSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBib3hlcyA9IGZlYXR1cmUuYm94ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwOyBiIDwgYm94ZXMubGVuZ3RoOyBiKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYm94ID0gYm94ZXNbYl07XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IGJveC5hbmNob3I7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGwgPSBuZXcgUG9pbnQoYm94LngxLCBib3gueTEgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG4gICAgICAgICAgICAgICAgdmFyIHRyID0gbmV3IFBvaW50KGJveC54MiwgYm94LnkxICogeVN0cmV0Y2gpLl9yb3RhdGUoYW5nbGUpO1xuICAgICAgICAgICAgICAgIHZhciBibCA9IG5ldyBQb2ludChib3gueDEsIGJveC55MiAqIHlTdHJldGNoKS5fcm90YXRlKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICB2YXIgYnIgPSBuZXcgUG9pbnQoYm94LngyLCBib3gueTIgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4Wm9vbSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDI1LCB0aGlzLmNvbGxpc2lvbi56b29tICsgTWF0aC5sb2coYm94Lm1heFNjYWxlKSAvIE1hdGguTE4yKSk7XG4gICAgICAgICAgICAgICAgdmFyIHBsYWNlbWVudFpvb20gPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNSwgdGhpcy5jb2xsaXNpb24uem9vbSArIE1hdGgubG9nKGJveC5wbGFjZW1lbnRTY2FsZSkgLyBNYXRoLkxOMikpO1xuXG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIHRsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdHIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCB0ciwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJyLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgYnIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCBibCwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdGwsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveC5jdXJyZW50LnZlcnRleExlbmd0aCArPSA4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSB7XG5cbiAgICB0aGlzLnggPSBhbmNob3IueDtcbiAgICB0aGlzLnkgPSBhbmNob3IueTtcbiAgICB0aGlzLmhhc1RleHQgPSAhIXNoYXBlZFRleHQ7XG4gICAgdGhpcy5oYXNJY29uID0gISFzaGFwZWRJY29uO1xuXG4gICAgaWYgKHRoaXMuaGFzVGV4dCkge1xuICAgICAgICB0aGlzLmdseXBoUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRHbHlwaFF1YWRzKGFuY2hvciwgc2hhcGVkVGV4dCwgdGV4dEJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIHRleHRBbG9uZ0xpbmUpIDogW107XG4gICAgICAgIHRoaXMudGV4dENvbGxpc2lvbkZlYXR1cmUgPSBuZXcgQ29sbGlzaW9uRmVhdHVyZShsaW5lLCBhbmNob3IsIHNoYXBlZFRleHQsIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0ljb24pIHtcbiAgICAgICAgdGhpcy5pY29uUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRJY29uUXVhZHMoYW5jaG9yLCBzaGFwZWRJY29uLCBpY29uQm94U2NhbGUsIGxpbmUsIGxheW91dCwgaWNvbkFsb25nTGluZSkgOiBbXTtcbiAgICAgICAgdGhpcy5pY29uQ29sbGlzaW9uRmVhdHVyZSA9IG5ldyBDb2xsaXNpb25GZWF0dXJlKGxpbmUsIGFuY2hvciwgc2hhcGVkSWNvbiwgaWNvbkJveFNjYWxlLCBpY29uUGFkZGluZywgaWNvbkFsb25nTGluZSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvb3JkaW5hdGU7XG5cbi8qKlxuICogQSBjb29yZGluYXRlIGlzIGEgY29sdW1uLCByb3csIHpvb20gY29tYmluYXRpb24sIG9mdGVuIHVzZWRcbiAqIGFzIHRoZSBkYXRhIGNvbXBvbmVudCBvZiBhIHRpbGUuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IGNvbHVtblxuICogQHBhcmFtIHtOdW1iZXJ9IHJvd1xuICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIENvb3JkaW5hdGUoY29sdW1uLCByb3csIHpvb20pIHtcbiAgICB0aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICB0aGlzLnJvdyA9IHJvdztcbiAgICB0aGlzLnpvb20gPSB6b29tO1xufVxuXG5Db29yZGluYXRlLnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGNsb25lIG9mIHRoaXMgY29vcmRpbmF0ZSB0aGF0IGNhbiBiZSBtdXRhdGVkIHdpdGhvdXRcbiAgICAgKiBjaGFuZ2luZyB0aGUgb3JpZ2luYWwgY29vcmRpbmF0ZVxuICAgICAqXG4gICAgICogQHJldHVybnMge0Nvb3JkaW5hdGV9IGNsb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC5jbG9uZSgpO1xuICAgICAqIC8vIHNpbmNlIGNvb3JkIGlzIGNsb25lZCwgbW9kaWZ5aW5nIGEgcHJvcGVydHkgb2YgYzIgZG9lc1xuICAgICAqIC8vIG5vdCBtb2RpZnkgaXQuXG4gICAgICogYzIuem9vbSA9IDI7XG4gICAgICovXG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUodGhpcy5jb2x1bW4sIHRoaXMucm93LCB0aGlzLnpvb20pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIHRoaXMgY29vcmRpbmF0ZSB0byBhIGdpdmVuIHpvb20gbGV2ZWwuIFRoaXMgcmV0dXJucyBhIG5ld1xuICAgICAqIGNvb3JkaW5hdGUgb2JqZWN0LCBub3QgbXV0YXRpbmcgdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gem9vbVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSB6b29tZWQgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC56b29tVG8oMSk7XG4gICAgICogYzIgLy8gZXF1YWxzIG5ldyBDb29yZGluYXRlKDAsIDAsIDEpO1xuICAgICAqL1xuICAgIHpvb21UbzogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl96b29tVG8oem9vbSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTdWJ0cmFjdCB0aGUgY29sdW1uIGFuZCByb3cgdmFsdWVzIG9mIHRoaXMgY29vcmRpbmF0ZSBmcm9tIHRob3NlXG4gICAgICogb2YgYW5vdGhlciBjb29yZGluYXRlLiBUaGUgb3RoZXIgY29vcmRpbmF0IHdpbGwgYmUgem9vbWVkIHRvIHRoZVxuICAgICAqIHNhbWUgbGV2ZWwgYXMgYHRoaXNgIGJlZm9yZSB0aGUgc3VidHJhY3Rpb24gb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGMgb3RoZXIgY29vcmRpbmF0ZVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSByZXN1bHRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN1YjogZnVuY3Rpb24oYykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWIoYyk7IH0sXG5cbiAgICBfem9vbVRvOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHZhciBzY2FsZSA9IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAqPSBzY2FsZTtcbiAgICAgICAgdGhpcy5yb3cgKj0gc2NhbGU7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfc3ViOiBmdW5jdGlvbihjKSB7XG4gICAgICAgIGMgPSBjLnpvb21Ubyh0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAtPSBjLmNvbHVtbjtcbiAgICAgICAgdGhpcy5yb3cgLT0gYy5yb3c7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nO1xuXG52YXIgd3JhcCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpLndyYXA7XG5cbi8qKlxuICogQ3JlYXRlIGEgbGF0aXR1ZGUsIGxvbmdpdHVkZSBvYmplY3QgZnJvbSBhIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcGFpciBpbiBkZWdyZWVzLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiBhIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcG9pbnQsIGluIGRlZ3JlZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gbGF0IGxhdGl0dWRlXG4gKiBAcGFyYW0ge251bWJlcn0gbG5nIGxvbmdpdHVkZVxuICogQGV4YW1wbGVcbiAqIHZhciBsYXRsbmcgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDM3Ljc2LCAtMTIyLjQ0KTtcbiAqL1xuZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nKSB7XG4gICAgaWYgKGlzTmFOKGxhdCkgfHwgaXNOYU4obG5nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgTGF0TG5nIG9iamVjdDogKCcgKyBsYXQgKyAnLCAnICsgbG5nICsgJyknKTtcbiAgICB9XG4gICAgdGhpcy5sYXQgPSArbGF0O1xuICAgIHRoaXMubG5nID0gK2xuZztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBuZXcgYExhdExuZ2Agb2JqZWN0IHdob3NlIGxvbmdpdHVkZSBpcyB3cmFwcGVkIHRvIHRoZSByYW5nZSAoLTE4MCwgMTgwKS5cbiAqXG4gKiBAcmV0dXJucyB7TGF0TG5nfSB3cmFwcGVkIExhdExuZyBvYmplY3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9pbnQgPSBtYXBib3hnbC5MYXRMbmcoMCwgMjAwKTtcbiAqIHZhciB3cmFwcGVkID0gcG9pbnQud3JhcCgpO1xuICogd3JhcHBlZC5sbmc7IC8vID0gLTE2MFxuICovXG5MYXRMbmcucHJvdG90eXBlLndyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHdyYXAodGhpcy5sbmcsIC0xODAsIDE4MCkpO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IGFuIGFycmF5IHRvIGEgYExhdExuZ2Agb2JqZWN0LCBvciByZXR1cm4gYW4gZXhpc3RpbmcgYExhdExuZ2Agb2JqZWN0XG4gKiB1bmNoYW5nZWQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fExhdExuZ30gaW5wdXQgYGlucHV0YCB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7TGF0TG5nfSBMYXRMbmcgb2JqZWN0IG9yIG9yaWdpbmFsIGlucHV0XG4gKiBAZXhhbXBsZVxuICogdmFyIGxsID0gbWFwYm94Z2wuTGF0TG5nLmNvbnZlcnQoWzEwLCAxMF0pO1xuICogdmFyIGxsMiA9IG5ldyBtYXBib3hnbC5MYXRMbmcoMTAsIDEwKTtcbiAqIGxsIC8vID0gbGwyXG4gKi9cbkxhdExuZy5jb252ZXJ0ID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKGlucHV0WzBdLCBpbnB1dFsxXSk7XG4gICAgfVxuICAgIHJldHVybiBpbnB1dDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nQm91bmRzO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJvdW5kaW5nIGJveCBmcm9tIHRoZSBnaXZlbiBwYWlyIG9mIHBvaW50cy4gSWYgcGFyYW1ldGVyZXMgYXJlIG9taXR0ZWQsIGEgYG51bGxgIGJvdW5kaW5nIGJveCBpcyBjcmVhdGVkLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdCb3VuZHNcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiByZWN0YW5ndWxhciBib3ggb24gdGhlIGVhcnRoLCBkZWZpbmVkIGJ5IGl0cyBzb3V0aHdlc3QgYW5kIG5vcnRoZWFzdCBwb2ludHMgaW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS5cbiAqIEBwYXJhbSB7TGF0TG5nfSBzdyBzb3V0aHdlc3RcbiAqIEBwYXJhbSB7TGF0TG5nfSBuZSBub3J0aGVhc3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgc3cgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDAsIDApO1xuICogdmFyIG5lID0gbmV3IG1hcGJveGdsLkxhdExuZygxMCwgLTEwKTtcbiAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKHN3LCBuZSk7XG4gKlxuICovXG5mdW5jdGlvbiBMYXRMbmdCb3VuZHMoc3csIG5lKSB7XG4gICAgaWYgKCFzdykgcmV0dXJuO1xuXG4gICAgdmFyIGxhdGxuZ3MgPSBuZSA/IFtzdywgbmVdIDogc3c7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB0aGlzLmV4dGVuZChsYXRsbmdzW2ldKTtcbiAgICB9XG59XG5cbkxhdExuZ0JvdW5kcy5wcm90b3R5cGUgPSB7XG5cbiAgICAvKipcbiAgICAgKiBFeHRlbmQgdGhlIGJvdW5kcyB0byBpbmNsdWRlIGEgZ2l2ZW4gTGF0TG5nIG9yIExhdExuZ0JvdW5kcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TGF0TG5nfExhdExuZ0JvdW5kc30gb2JqIG9iamVjdCB0byBleHRlbmQgdG9cbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nQm91bmRzfSBgdGhpc2BcbiAgICAgKi9cbiAgICBleHRlbmQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICB2YXIgc3cgPSB0aGlzLl9zdyxcbiAgICAgICAgICAgIG5lID0gdGhpcy5fbmUsXG4gICAgICAgICAgICBzdzIsIG5lMjtcblxuICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgICAgICBzdzIgPSBvYmo7XG4gICAgICAgICAgICBuZTIgPSBvYmo7XG5cbiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcbiAgICAgICAgICAgIHN3MiA9IG9iai5fc3c7XG4gICAgICAgICAgICBuZTIgPSBvYmouX25lO1xuXG4gICAgICAgICAgICBpZiAoIXN3MiB8fCAhbmUyKSByZXR1cm4gdGhpcztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKExhdExuZy5jb252ZXJ0KG9iaikgfHwgTGF0TG5nQm91bmRzLmNvbnZlcnQob2JqKSkgOiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzdyAmJiAhbmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N3ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcbiAgICAgICAgICAgIHRoaXMuX25lID0gbmV3IExhdExuZyhuZTIubGF0LCBuZTIubG5nKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcbiAgICAgICAgICAgIHN3LmxuZyA9IE1hdGgubWluKHN3Mi5sbmcsIHN3LmxuZyk7XG4gICAgICAgICAgICBuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xuICAgICAgICAgICAgbmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHBvaW50IGVxdWlkaXN0YW50IGZyb20gdGhpcyBib3gncyBjb3JuZXJzXG4gICAgICogQHJldHVybnMge0xhdExuZ30gY2VudGVycG9pbnRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygxMCwgMTApLFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygtMTAsIC0xMCk7XG4gICAgICogYm91bmRzLmdldENlbnRlcigpOyAvLyBlcXVhbHMgbWFwYm94Z2wuTGF0TG5nKDAsIDApXG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmcoKHRoaXMuX3N3LmxhdCArIHRoaXMuX25lLmxhdCkgLyAyLCAodGhpcy5fc3cubG5nICsgdGhpcy5fbmUubG5nKSAvIDIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGh3ZXN0IGNvcm5lclxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9IHNvdXRod2VzdFxuICAgICAqL1xuICAgIGdldFNvdXRoV2VzdDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdzsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBub3J0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbm9ydGhlYXN0XG4gICAgICovXG4gICAgZ2V0Tm9ydGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRod2VzdCBjb3JuZXJcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBub3J0aHdlc3RcbiAgICAgKi9cbiAgICBnZXROb3J0aFdlc3Q6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldE5vcnRoKCksIHRoaXMuZ2V0V2VzdCgpKTsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBzb3V0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gc291dGhlYXN0XG4gICAgICovXG4gICAgZ2V0U291dGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgd2VzdCBlZGdlIGxvbmdpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHdlc3RcbiAgICAgKi9cbiAgICBnZXRXZXN0OiAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdy5sbmc7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGggZWRnZSBsYXRpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHNvdXRoXG4gICAgICovXG4gICAgZ2V0U291dGg6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fc3cubGF0OyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IGVhc3QgZWRnZSBsb25naXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBlYXN0XG4gICAgICovXG4gICAgZ2V0RWFzdDogIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fbmUubG5nOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRoIGVkZ2UgbGF0aXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBub3J0aFxuICAgICAqL1xuICAgIGdldE5vcnRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lLmxhdDsgfVxufTtcblxuLyoqXG4gKiBjb25zdHJ1Y3RzIExhdExuZ0JvdW5kcyBmcm9tIGFuIGFycmF5IGlmIG5lY2Vzc2FyeVxuICogQHBhcmFtIHtMYXRMbmdCb3VuZHN8Kn0gYSBhbnkgaW5wdXRcbiAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN8ZmFsc2V9XG4gKiBAZXhhbXBsZVxuICogLy8gY2FsbHMgTGF0TG5nLmNvbnZlcnQgaW50ZXJuYWxseSB0b1xuICogLy8gc3VwcG9ydCBhcnJheXMgYXMgbGF0bG5nIHZhbHVlc1xuICogTGF0TG5nQm91bmRzLmNvbnZlcnQoW1stMTAsIC0xMF0sIFsxMCwgMTBdXSk7XG4gKi9cbkxhdExuZ0JvdW5kcy5jb252ZXJ0ID0gZnVuY3Rpb24gKGEpIHtcbiAgICBpZiAoIWEgfHwgYSBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykgcmV0dXJuIGE7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpLFxuICAgIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuL2Nvb3JkaW5hdGUnKSxcbiAgICB3cmFwID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJykud3JhcCxcbiAgICBpbnRlcnAgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyksXG4gICAgdmVjNCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLnZlYzQsXG4gICAgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhbnNmb3JtO1xuXG4vKlxuICogQSBzaW5nbGUgdHJhbnNmb3JtLCBnZW5lcmFsbHkgdXNlZCBmb3IgYSBzaW5nbGUgdGlsZSB0byBiZVxuICogc2NhbGVkLCByb3RhdGVkLCBhbmQgem9vbWVkLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtaW5ab29tXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4Wm9vbVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gVHJhbnNmb3JtKG1pblpvb20sIG1heFpvb20pIHtcbiAgICB0aGlzLnRpbGVTaXplID0gNTEyOyAvLyBjb25zdGFudFxuXG4gICAgdGhpcy5fbWluWm9vbSA9IG1pblpvb20gfHwgMDtcbiAgICB0aGlzLl9tYXhab29tID0gbWF4Wm9vbSB8fCAyMjtcblxuICAgIHRoaXMubGF0UmFuZ2UgPSBbLTg1LjA1MTEzLCA4NS4wNTExM107XG5cbiAgICB0aGlzLndpZHRoID0gMDtcbiAgICB0aGlzLmhlaWdodCA9IDA7XG4gICAgdGhpcy56b29tID0gMDtcbiAgICB0aGlzLmNlbnRlciA9IG5ldyBMYXRMbmcoMCwgMCk7XG4gICAgdGhpcy5hbmdsZSA9IDA7XG4gICAgdGhpcy5fYWx0aXR1ZGUgPSAxLjU7XG4gICAgdGhpcy5fcGl0Y2ggPSAwO1xufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlID0ge1xuICAgIGdldCBtaW5ab29tKCkgeyByZXR1cm4gdGhpcy5fbWluWm9vbTsgfSxcbiAgICBzZXQgbWluWm9vbSh6b29tKSB7XG4gICAgICAgIHRoaXMuX21pblpvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnpvb20gPSBNYXRoLm1heCh0aGlzLnpvb20sIHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXQgbWF4Wm9vbSgpIHsgcmV0dXJuIHRoaXMuX21heFpvb207IH0sXG4gICAgc2V0IG1heFpvb20oem9vbSkge1xuICAgICAgICB0aGlzLl9tYXhab29tID0gem9vbTtcbiAgICAgICAgdGhpcy56b29tID0gTWF0aC5taW4odGhpcy56b29tLCB6b29tKTtcbiAgICB9LFxuXG4gICAgZ2V0IHdvcmxkU2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUgKiB0aGlzLnNjYWxlO1xuICAgIH0sXG5cbiAgICBnZXQgY2VudGVyUG9pbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemUuX2RpdigyKTtcbiAgICB9LFxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuICAgIH0sXG5cbiAgICBnZXQgYmVhcmluZygpIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLmFuZ2xlIC8gTWF0aC5QSSAqIDE4MDtcbiAgICB9LFxuICAgIHNldCBiZWFyaW5nKGJlYXJpbmcpIHtcbiAgICAgICAgdGhpcy5hbmdsZSA9IC13cmFwKGJlYXJpbmcsIC0xODAsIDE4MCkgKiBNYXRoLlBJIC8gMTgwO1xuICAgIH0sXG5cbiAgICBnZXQgcGl0Y2goKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9waXRjaCAvIE1hdGguUEkgKiAxODA7XG4gICAgfSxcbiAgICBzZXQgcGl0Y2gocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5fcGl0Y2ggPSBNYXRoLm1pbig2MCwgcGl0Y2gpIC8gMTgwICogTWF0aC5QSTtcbiAgICB9LFxuXG4gICAgZ2V0IGFsdGl0dWRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWx0aXR1ZGU7XG4gICAgfSxcbiAgICBzZXQgYWx0aXR1ZGUoYWx0aXR1ZGUpIHtcbiAgICAgICAgdGhpcy5fYWx0aXR1ZGUgPSBNYXRoLm1heCgwLjc1LCBhbHRpdHVkZSk7XG4gICAgfSxcblxuICAgIGdldCB6b29tKCkgeyByZXR1cm4gdGhpcy5fem9vbTsgfSxcbiAgICBzZXQgem9vbSh6b29tKSB7XG4gICAgICAgIHpvb20gPSBNYXRoLm1pbihNYXRoLm1heCh6b29tLCB0aGlzLm1pblpvb20pLCB0aGlzLm1heFpvb20pO1xuICAgICAgICB0aGlzLl96b29tID0gem9vbTtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHRoaXMuem9vbVNjYWxlKHpvb20pO1xuICAgICAgICB0aGlzLnRpbGVab29tID0gTWF0aC5mbG9vcih6b29tKTtcbiAgICAgICAgdGhpcy56b29tRnJhY3Rpb24gPSB6b29tIC0gdGhpcy50aWxlWm9vbTtcbiAgICAgICAgdGhpcy5fY29uc3RyYWluKCk7XG4gICAgfSxcblxuICAgIHpvb21TY2FsZTogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gTWF0aC5wb3coMiwgem9vbSk7IH0sXG4gICAgc2NhbGVab29tOiBmdW5jdGlvbihzY2FsZSkgeyByZXR1cm4gTWF0aC5sb2coc2NhbGUpIC8gTWF0aC5MTjI7IH0sXG5cbiAgICBwcm9qZWN0OiBmdW5jdGlvbihsYXRsbmcsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IFBvaW50KFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcsIHdvcmxkU2l6ZSksXG4gICAgICAgICAgICB0aGlzLmxhdFkobGF0bG5nLmxhdCwgd29ybGRTaXplKSk7XG4gICAgfSxcblxuICAgIHVucHJvamVjdDogZnVuY3Rpb24ocG9pbnQsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZyhcbiAgICAgICAgICAgIHRoaXMueUxhdChwb2ludC55LCB3b3JsZFNpemUpLFxuICAgICAgICAgICAgdGhpcy54TG5nKHBvaW50LngsIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBnZXQgeCgpIHsgcmV0dXJuIHRoaXMubG5nWCh0aGlzLmNlbnRlci5sbmcpOyB9LFxuICAgIGdldCB5KCkgeyByZXR1cm4gdGhpcy5sYXRZKHRoaXMuY2VudGVyLmxhdCk7IH0sXG5cbiAgICBnZXQgcG9pbnQoKSB7IHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpOyB9LFxuXG4gICAgLyoqXG4gICAgICogbGF0L2xvbiA8LT4gYWJzb2x1dGUgcGl4ZWwgY29vcmRzIGNvbnZlcnNpb25cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbG9uXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG5nWDogZnVuY3Rpb24obG9uLCB3b3JsZFNpemUpIHtcbiAgICAgICAgcmV0dXJuICgxODAgKyBsb24pICogKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLyAzNjA7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBsYXRpdHVkZSB0byBhYnNvbHV0ZSB5IGNvb3JkXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGF0XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbGF0WTogZnVuY3Rpb24obGF0LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkgPSAxODAgLyBNYXRoLlBJICogTWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSSAvIDQgKyBsYXQgKiBNYXRoLlBJIC8gMzYwKSk7XG4gICAgICAgIHJldHVybiAoMTgwIC0geSkgKiAod29ybGRTaXplIHx8IHRoaXMud29ybGRTaXplKSAvIDM2MDtcbiAgICB9LFxuXG4gICAgeExuZzogZnVuY3Rpb24oeCwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiB4ICogMzYwIC8gKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLSAxODA7XG4gICAgfSxcbiAgICB5TGF0OiBmdW5jdGlvbih5LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkyID0gMTgwIC0geSAqIDM2MCAvICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpO1xuICAgICAgICByZXR1cm4gMzYwIC8gTWF0aC5QSSAqIE1hdGguYXRhbihNYXRoLmV4cCh5MiAqIE1hdGguUEkgLyAxODApKSAtIDkwO1xuICAgIH0sXG5cbiAgICBwYW5CeTogZnVuY3Rpb24ob2Zmc2V0KSB7XG4gICAgICAgIHZhciBwb2ludCA9IHRoaXMuY2VudGVyUG9pbnQuX2FkZChvZmZzZXQpO1xuICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMucG9pbnRMb2NhdGlvbihwb2ludCk7XG4gICAgICAgIHRoaXMuX2NvbnN0cmFpbigpO1xuICAgIH0sXG5cbiAgICBzZXRMb2NhdGlvbkF0UG9pbnQ6IGZ1bmN0aW9uKGxhdGxuZywgcG9pbnQpIHtcbiAgICAgICAgdmFyIGMgPSB0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpO1xuICAgICAgICB2YXIgY29vcmRBdFBvaW50ID0gdGhpcy5wb2ludENvb3JkaW5hdGUocG9pbnQpO1xuICAgICAgICB2YXIgY29vcmRDZW50ZXIgPSB0aGlzLnBvaW50Q29vcmRpbmF0ZSh0aGlzLmNlbnRlclBvaW50KTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlID0gY29vcmRBdFBvaW50Ll9zdWIoYyk7XG4gICAgICAgIHRoaXMuY2VudGVyID0gdGhpcy5jb29yZGluYXRlTG9jYXRpb24oY29vcmRDZW50ZXIuX3N1Yih0cmFuc2xhdGUpKTtcblxuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgc2V0Wm9vbUFyb3VuZDogZnVuY3Rpb24oem9vbSwgY2VudGVyKSB7XG4gICAgICAgIHZhciBwID0gdGhpcy5sb2NhdGlvblBvaW50KGNlbnRlcik7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHRoaXMuc2V0TG9jYXRpb25BdFBvaW50KGNlbnRlciwgcCk7XG4gICAgfSxcblxuICAgIHNldEJlYXJpbmdBcm91bmQ6IGZ1bmN0aW9uKGJlYXJpbmcsIGNlbnRlcikge1xuICAgICAgICB2YXIgcCA9IHRoaXMubG9jYXRpb25Qb2ludChjZW50ZXIpO1xuICAgICAgICB0aGlzLmJlYXJpbmcgPSBiZWFyaW5nO1xuICAgICAgICB0aGlzLnNldExvY2F0aW9uQXRQb2ludChjZW50ZXIsIHApO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGxvY2F0aW9uLCByZXR1cm4gdGhlIHNjcmVlbiBwb2ludCB0aGF0IGNvcnJlc3BvbmRzIHRvIGl0XG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZyBsb2NhdGlvblxuICAgICAqIEByZXR1cm5zIHtQb2ludH0gc2NyZWVuIHBvaW50XG4gICAgICovXG4gICAgbG9jYXRpb25Qb2ludDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBwb2ludCBvbiBzY3JlZW4sIHJldHVybiBpdHMgbGF0bG5nXG4gICAgICogQHBhcmFtIHtQb2ludH0gcCBzY3JlZW4gcG9pbnRcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBsYXRsbmcgbG9jYXRpb25cbiAgICAgKi9cbiAgICBwb2ludExvY2F0aW9uOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZShwKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGxhdGxuZywgcmV0dXJuIGFuIHVucm91bmRlZFxuICAgICAqIGNvb3JkaW5hdGUgdGhhdCByZXByZXNlbnRzIGl0IGF0IHRoaXMgdHJhbnNmb3JtJ3Mgem9vbSBsZXZlbCBhbmRcbiAgICAgKiB3b3JsZHNpemUuXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfVxuICAgICAqL1xuICAgIGxvY2F0aW9uQ29vcmRpbmF0ZTogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHZhciBrID0gdGhpcy56b29tU2NhbGUodGhpcy50aWxlWm9vbSkgLyB0aGlzLndvcmxkU2l6ZTtcbiAgICAgICAgcmV0dXJuIG5ldyBDb29yZGluYXRlKFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcpICogayxcbiAgICAgICAgICAgIHRoaXMubGF0WShsYXRsbmcubGF0KSAqIGssXG4gICAgICAgICAgICB0aGlzLnRpbGVab29tKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBDb29yZGluYXRlLCByZXR1cm4gaXRzIGdlb2dyYXBoaWNhbCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbGF0bG5nXG4gICAgICovXG4gICAgY29vcmRpbmF0ZUxvY2F0aW9uOiBmdW5jdGlvbihjb29yZCkge1xuICAgICAgICB2YXIgd29ybGRTaXplID0gdGhpcy56b29tU2NhbGUoY29vcmQuem9vbSk7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKFxuICAgICAgICAgICAgdGhpcy55TGF0KGNvb3JkLnJvdywgd29ybGRTaXplKSxcbiAgICAgICAgICAgIHRoaXMueExuZyhjb29yZC5jb2x1bW4sIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBwb2ludENvb3JkaW5hdGU6IGZ1bmN0aW9uKHAsIHRhcmdldFopIHtcblxuICAgICAgICBpZiAodGFyZ2V0WiA9PT0gdW5kZWZpbmVkKSB0YXJnZXRaID0gMDtcblxuICAgICAgICB2YXIgbWF0cml4ID0gdGhpcy5jb29yZGluYXRlUG9pbnRNYXRyaXgodGhpcy50aWxlWm9vbSk7XG4gICAgICAgIHZhciBpbnZlcnRlZCA9IG1hdDQuaW52ZXJ0KG5ldyBGbG9hdDY0QXJyYXkoMTYpLCBtYXRyaXgpO1xuXG4gICAgICAgIGlmICghaW52ZXJ0ZWQpIHRocm93IFwiZmFpbGVkIHRvIGludmVydCBtYXRyaXhcIjtcblxuICAgICAgICAvLyBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSBjb3JyZWN0IHByb2plY3RlZCB6IHZhbHVlIGZvciB0aGUgcG9pbnQsXG4gICAgICAgIC8vIHVucHJvamVjdCB0d28gcG9pbnRzIHRvIGdldCBhIGxpbmUgYW5kIHRoZW4gZmluZCB0aGUgcG9pbnQgb24gdGhhdFxuICAgICAgICAvLyBsaW5lIHdpdGggej0wXG5cbiAgICAgICAgdmFyIGNvb3JkMCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW3AueCwgcC55LCAwLCAxXSwgaW52ZXJ0ZWQpO1xuICAgICAgICB2YXIgY29vcmQxID0gdmVjNC50cmFuc2Zvcm1NYXQ0KFtdLCBbcC54LCBwLnksIDEsIDFdLCBpbnZlcnRlZCk7XG5cbiAgICAgICAgdmFyIHcwID0gY29vcmQwWzNdO1xuICAgICAgICB2YXIgdzEgPSBjb29yZDFbM107XG4gICAgICAgIHZhciB4MCA9IGNvb3JkMFswXSAvIHcwO1xuICAgICAgICB2YXIgeDEgPSBjb29yZDFbMF0gLyB3MTtcbiAgICAgICAgdmFyIHkwID0gY29vcmQwWzFdIC8gdzA7XG4gICAgICAgIHZhciB5MSA9IGNvb3JkMVsxXSAvIHcxO1xuICAgICAgICB2YXIgejAgPSBjb29yZDBbMl0gLyB3MDtcbiAgICAgICAgdmFyIHoxID0gY29vcmQxWzJdIC8gdzE7XG5cblxuICAgICAgICB2YXIgdCA9IHowID09PSB6MSA/IDAgOiAodGFyZ2V0WiAtIHowKSAvICh6MSAtIHowKTtcblxuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUoXG4gICAgICAgICAgICBpbnRlcnAoeDAsIHgxLCB0KSxcbiAgICAgICAgICAgIGludGVycCh5MCwgeTEsIHQpLFxuICAgICAgICAgICAgdGhpcy50aWxlWm9vbSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgY29vcmRpbmF0ZSwgcmV0dXJuIHRoZSBzY3JlZW4gcG9pbnQgdGhhdCBjb3JyZXNwb25kcyB0byBpdFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7UG9pbnR9IHNjcmVlbiBwb2ludFxuICAgICAqL1xuICAgIGNvb3JkaW5hdGVQb2ludDogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMuY29vcmRpbmF0ZVBvaW50TWF0cml4KGNvb3JkLnpvb20pO1xuICAgICAgICB2YXIgcCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW2Nvb3JkLmNvbHVtbiwgY29vcmQucm93LCAwLCAxXSwgbWF0cml4KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChwWzBdIC8gcFszXSwgcFsxXSAvIHBbM10pO1xuICAgIH0sXG5cbiAgICBjb29yZGluYXRlUG9pbnRNYXRyaXg6IGZ1bmN0aW9uKHopIHtcbiAgICAgICAgdmFyIHByb2ogPSB0aGlzLmdldFByb2pNYXRyaXgoKTtcbiAgICAgICAgdmFyIHNjYWxlID0gdGhpcy53b3JsZFNpemUgLyB0aGlzLnpvb21TY2FsZSh6KTtcbiAgICAgICAgbWF0NC5zY2FsZShwcm9qLCBwcm9qLCBbc2NhbGUsIHNjYWxlLCAxXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkocHJvaiwgdGhpcy5nZXRQaXhlbE1hdHJpeCgpLCBwcm9qKTtcbiAgICAgICAgcmV0dXJuIHByb2o7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIGNvbnZlcnRzIGdsIGNvb3JkaW5hdGVzIC0xLi4xIHRvIHBpeGVscyAwLi53aWR0aFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IG1hdHJpeFxuICAgICAqL1xuICAgIGdldFBpeGVsTWF0cml4OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG0gPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFt0aGlzLndpZHRoIC8gMiwgLXRoaXMuaGVpZ2h0IC8gMiwgMV0pO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbMSwgLTEsIDBdKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgfSxcblxuICAgIF9jb25zdHJhaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VudGVyKSByZXR1cm47XG5cbiAgICAgICAgdmFyIG1pblksIG1heFksIG1pblgsIG1heFgsIHN5LCBzeCwgeDIsIHkyLFxuICAgICAgICAgICAgc2l6ZSA9IHRoaXMuc2l6ZTtcblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgbWluWSA9IHRoaXMubGF0WSh0aGlzLmxhdFJhbmdlWzFdKTtcbiAgICAgICAgICAgIG1heFkgPSB0aGlzLmxhdFkodGhpcy5sYXRSYW5nZVswXSk7XG4gICAgICAgICAgICBzeSA9IG1heFkgLSBtaW5ZIDwgc2l6ZS55ID8gc2l6ZS55IC8gKG1heFkgLSBtaW5ZKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgbWluWCA9IHRoaXMubG5nWCh0aGlzLmxuZ1JhbmdlWzBdKTtcbiAgICAgICAgICAgIG1heFggPSB0aGlzLmxuZ1godGhpcy5sbmdSYW5nZVsxXSk7XG4gICAgICAgICAgICBzeCA9IG1heFggLSBtaW5YIDwgc2l6ZS54ID8gc2l6ZS54IC8gKG1heFggLSBtaW5YKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob3cgbXVjaCB0aGUgbWFwIHNob3VsZCBzY2FsZSB0byBmaXQgdGhlIHNjcmVlbiBpbnRvIGdpdmVuIGxhdGl0dWRlL2xvbmdpdHVkZSByYW5nZXNcbiAgICAgICAgdmFyIHMgPSBNYXRoLm1heChzeCB8fCAwLCBzeSB8fCAwKTtcblxuICAgICAgICBpZiAocykge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnVucHJvamVjdChuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgc3ggPyAobWF4WCArIG1pblgpIC8gMiA6IHRoaXMueCxcbiAgICAgICAgICAgICAgICBzeSA/IChtYXhZICsgbWluWSkgLyAyIDogdGhpcy55KSk7XG4gICAgICAgICAgICB0aGlzLnpvb20gKz0gdGhpcy5zY2FsZVpvb20ocyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHkgPSB0aGlzLnksXG4gICAgICAgICAgICAgICAgaDIgPSBzaXplLnkgLyAyO1xuXG4gICAgICAgICAgICBpZiAoeSAtIGgyIDwgbWluWSkgeTIgPSBtaW5ZICsgaDI7XG4gICAgICAgICAgICBpZiAoeSArIGgyID4gbWF4WSkgeTIgPSBtYXhZIC0gaDI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHggPSB0aGlzLngsXG4gICAgICAgICAgICAgICAgdzIgPSBzaXplLnggLyAyO1xuXG4gICAgICAgICAgICBpZiAoeCAtIHcyIDwgbWluWCkgeDIgPSBtaW5YICsgdzI7XG4gICAgICAgICAgICBpZiAoeCArIHcyID4gbWF4WCkgeDIgPSBtYXhYIC0gdzI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwYW4gdGhlIG1hcCBpZiB0aGUgc2NyZWVuIGdvZXMgb2ZmIHRoZSByYW5nZVxuICAgICAgICBpZiAoeDIgIT09IHVuZGVmaW5lZCB8fCB5MiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMudW5wcm9qZWN0KG5ldyBQb2ludChcbiAgICAgICAgICAgICAgICB4MiAhPT0gdW5kZWZpbmVkID8geDIgOiB0aGlzLngsXG4gICAgICAgICAgICAgICAgeTIgIT09IHVuZGVmaW5lZCA/IHkyIDogdGhpcy55KSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZ2V0UHJvak1hdHJpeDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtID0gbmV3IEZsb2F0NjRBcnJheSgxNik7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgY2VudGVyIHBvaW50IHRvIHRoZSBjZW50ZXIgdG9wIGluIGFsdGl0dWRlIHVuaXRzIHVzaW5nIGxhdyBvZiBzaW5lcy5cbiAgICAgICAgdmFyIGhhbGZGb3YgPSBNYXRoLmF0YW4oMC41IC8gdGhpcy5hbHRpdHVkZSk7XG4gICAgICAgIHZhciB0b3BIYWxmU3VyZmFjZURpc3RhbmNlID0gTWF0aC5zaW4oaGFsZkZvdikgKiB0aGlzLmFsdGl0dWRlIC8gTWF0aC5zaW4oTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCAtIGhhbGZGb3YpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgeiB2YWx1ZSBvZiB0aGUgZmFydGhlc3QgZnJhZ21lbnQgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAgICAgIHZhciBmYXJaID0gTWF0aC5jb3MoTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCkgKiB0b3BIYWxmU3VyZmFjZURpc3RhbmNlICsgdGhpcy5hbHRpdHVkZTtcblxuICAgICAgICBtYXQ0LnBlcnNwZWN0aXZlKG0sIDIgKiBNYXRoLmF0YW4oKHRoaXMuaGVpZ2h0IC8gMikgLyB0aGlzLmFsdGl0dWRlKSwgdGhpcy53aWR0aCAvIHRoaXMuaGVpZ2h0LCAwLjEsIGZhclopO1xuXG4gICAgICAgIG1hdDQudHJhbnNsYXRlKG0sIG0sIFswLCAwLCAtdGhpcy5hbHRpdHVkZV0pO1xuXG4gICAgICAgIC8vIEFmdGVyIHRoZSByb3RhdGVYLCB6IHZhbHVlcyBhcmUgaW4gcGl4ZWwgdW5pdHMuIENvbnZlcnQgdGhlbSB0b1xuICAgICAgICAvLyBhbHRpdHVkZSB1bml0ZXMuIDEgYWx0aXR1ZGUgdW5pdCA9IHRoZSBzY3JlZW4gaGVpZ2h0LlxuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFsxLCAtMSwgMSAvIHRoaXMuaGVpZ2h0XSk7XG5cbiAgICAgICAgbWF0NC5yb3RhdGVYKG0sIG0sIHRoaXMuX3BpdGNoKTtcbiAgICAgICAgbWF0NC5yb3RhdGVaKG0sIG0sIHRoaXMuYW5nbGUpO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbLXRoaXMueCwgLXRoaXMueSwgMF0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBGb250IGRhdGEgRnJvbSBIZXJzaGV5IFNpbXBsZXggRm9udFxuLy8gaHR0cDovL3BhdWxib3Vya2UubmV0L2RhdGFmb3JtYXRzL2hlcnNoZXkvXG52YXIgc2ltcGxleEZvbnQgPSB7XG4gICAgXCIgXCI6IFsxNiwgW11dLFxuICAgIFwiIVwiOiBbMTAsIFs1LCAyMSwgNSwgNywgLTEsIC0xLCA1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCJcXFwiXCI6IFsxNiwgWzQsIDIxLCA0LCAxNCwgLTEsIC0xLCAxMiwgMjEsIDEyLCAxNF1dLFxuICAgIFwiI1wiOiBbMjEsIFsxMSwgMjUsIDQsIC03LCAtMSwgLTEsIDE3LCAyNSwgMTAsIC03LCAtMSwgLTEsIDQsIDEyLCAxOCwgMTIsIC0xLCAtMSwgMywgNiwgMTcsIDZdXSxcbiAgICBcIiRcIjogWzIwLCBbOCwgMjUsIDgsIC00LCAtMSwgLTEsIDEyLCAyNSwgMTIsIC00LCAtMSwgLTEsIDE3LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxLCA1LCAyMCwgMywgMTgsIDMsIDE2LCA0LCAxNCwgNSwgMTMsIDcsIDEyLCAxMywgMTAsIDE1LCA5LCAxNiwgOCwgMTcsIDYsIDE3LCAzLCAxNSwgMSwgMTIsIDAsIDgsIDAsIDUsIDEsIDMsIDNdXSxcbiAgICBcIiVcIjogWzI0LCBbMjEsIDIxLCAzLCAwLCAtMSwgLTEsIDgsIDIxLCAxMCwgMTksIDEwLCAxNywgOSwgMTUsIDcsIDE0LCA1LCAxNCwgMywgMTYsIDMsIDE4LCA0LCAyMCwgNiwgMjEsIDgsIDIxLCAxMCwgMjAsIDEzLCAxOSwgMTYsIDE5LCAxOSwgMjAsIDIxLCAyMSwgLTEsIC0xLCAxNywgNywgMTUsIDYsIDE0LCA0LCAxNCwgMiwgMTYsIDAsIDE4LCAwLCAyMCwgMSwgMjEsIDMsIDIxLCA1LCAxOSwgNywgMTcsIDddXSxcbiAgICBcIiZcIjogWzI2LCBbMjMsIDEyLCAyMywgMTMsIDIyLCAxNCwgMjEsIDE0LCAyMCwgMTMsIDE5LCAxMSwgMTcsIDYsIDE1LCAzLCAxMywgMSwgMTEsIDAsIDcsIDAsIDUsIDEsIDQsIDIsIDMsIDQsIDMsIDYsIDQsIDgsIDUsIDksIDEyLCAxMywgMTMsIDE0LCAxNCwgMTYsIDE0LCAxOCwgMTMsIDIwLCAxMSwgMjEsIDksIDIwLCA4LCAxOCwgOCwgMTYsIDksIDEzLCAxMSwgMTAsIDE2LCAzLCAxOCwgMSwgMjAsIDAsIDIyLCAwLCAyMywgMSwgMjMsIDJdXSxcbiAgICBcIidcIjogWzEwLCBbNSwgMTksIDQsIDIwLCA1LCAyMSwgNiwgMjAsIDYsIDE4LCA1LCAxNiwgNCwgMTVdXSxcbiAgICBcIihcIjogWzE0LCBbMTEsIDI1LCA5LCAyMywgNywgMjAsIDUsIDE2LCA0LCAxMSwgNCwgNywgNSwgMiwgNywgLTIsIDksIC01LCAxMSwgLTddXSxcbiAgICBcIilcIjogWzE0LCBbMywgMjUsIDUsIDIzLCA3LCAyMCwgOSwgMTYsIDEwLCAxMSwgMTAsIDcsIDksIDIsIDcsIC0yLCA1LCAtNSwgMywgLTddXSxcbiAgICBcIipcIjogWzE2LCBbOCwgMjEsIDgsIDksIC0xLCAtMSwgMywgMTgsIDEzLCAxMiwgLTEsIC0xLCAxMywgMTgsIDMsIDEyXV0sXG4gICAgXCIrXCI6IFsyNiwgWzEzLCAxOCwgMTMsIDAsIC0xLCAtMSwgNCwgOSwgMjIsIDldXSxcbiAgICBcIixcIjogWzEwLCBbNiwgMSwgNSwgMCwgNCwgMSwgNSwgMiwgNiwgMSwgNiwgLTEsIDUsIC0zLCA0LCAtNF1dLFxuICAgIFwiLVwiOiBbMjYsIFs0LCA5LCAyMiwgOV1dLFxuICAgIFwiLlwiOiBbMTAsIFs1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCIvXCI6IFsyMiwgWzIwLCAyNSwgMiwgLTddXSxcbiAgICBcIjBcIjogWzIwLCBbOSwgMjEsIDYsIDIwLCA0LCAxNywgMywgMTIsIDMsIDksIDQsIDQsIDYsIDEsIDksIDAsIDExLCAwLCAxNCwgMSwgMTYsIDQsIDE3LCA5LCAxNywgMTIsIDE2LCAxNywgMTQsIDIwLCAxMSwgMjEsIDksIDIxXV0sXG4gICAgXCIxXCI6IFsyMCwgWzYsIDE3LCA4LCAxOCwgMTEsIDIxLCAxMSwgMF1dLFxuICAgIFwiMlwiOiBbMjAsIFs0LCAxNiwgNCwgMTcsIDUsIDE5LCA2LCAyMCwgOCwgMjEsIDEyLCAyMSwgMTQsIDIwLCAxNSwgMTksIDE2LCAxNywgMTYsIDE1LCAxNSwgMTMsIDEzLCAxMCwgMywgMCwgMTcsIDBdXSxcbiAgICBcIjNcIjogWzIwLCBbNSwgMjEsIDE2LCAyMSwgMTAsIDEzLCAxMywgMTMsIDE1LCAxMiwgMTYsIDExLCAxNywgOCwgMTcsIDYsIDE2LCAzLCAxNCwgMSwgMTEsIDAsIDgsIDAsIDUsIDEsIDQsIDIsIDMsIDRdXSxcbiAgICBcIjRcIjogWzIwLCBbMTMsIDIxLCAzLCA3LCAxOCwgNywgLTEsIC0xLCAxMywgMjEsIDEzLCAwXV0sXG4gICAgXCI1XCI6IFsyMCwgWzE1LCAyMSwgNSwgMjEsIDQsIDEyLCA1LCAxMywgOCwgMTQsIDExLCAxNCwgMTQsIDEzLCAxNiwgMTEsIDE3LCA4LCAxNywgNiwgMTYsIDMsIDE0LCAxLCAxMSwgMCwgOCwgMCwgNSwgMSwgNCwgMiwgMywgNF1dLFxuICAgIFwiNlwiOiBbMjAsIFsxNiwgMTgsIDE1LCAyMCwgMTIsIDIxLCAxMCwgMjEsIDcsIDIwLCA1LCAxNywgNCwgMTIsIDQsIDcsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMSwgMCwgMTQsIDEsIDE2LCAzLCAxNywgNiwgMTcsIDcsIDE2LCAxMCwgMTQsIDEyLCAxMSwgMTMsIDEwLCAxMywgNywgMTIsIDUsIDEwLCA0LCA3XV0sXG4gICAgXCI3XCI6IFsyMCwgWzE3LCAyMSwgNywgMCwgLTEsIC0xLCAzLCAyMSwgMTcsIDIxXV0sXG4gICAgXCI4XCI6IFsyMCwgWzgsIDIxLCA1LCAyMCwgNCwgMTgsIDQsIDE2LCA1LCAxNCwgNywgMTMsIDExLCAxMiwgMTQsIDExLCAxNiwgOSwgMTcsIDcsIDE3LCA0LCAxNiwgMiwgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCA0LCAyLCAzLCA0LCAzLCA3LCA0LCA5LCA2LCAxMSwgOSwgMTIsIDEzLCAxMywgMTUsIDE0LCAxNiwgMTYsIDE2LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxXV0sXG4gICAgXCI5XCI6IFsyMCwgWzE2LCAxNCwgMTUsIDExLCAxMywgOSwgMTAsIDgsIDksIDgsIDYsIDksIDQsIDExLCAzLCAxNCwgMywgMTUsIDQsIDE4LCA2LCAyMCwgOSwgMjEsIDEwLCAyMSwgMTMsIDIwLCAxNSwgMTgsIDE2LCAxNCwgMTYsIDksIDE1LCA0LCAxMywgMSwgMTAsIDAsIDgsIDAsIDUsIDEsIDQsIDNdXSxcbiAgICBcIjpcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDUsIDIsIDQsIDEsIDUsIDAsIDYsIDEsIDUsIDJdXSxcbiAgICBcIjtcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDYsIDEsIDUsIDAsIDQsIDEsIDUsIDIsIDYsIDEsIDYsIC0xLCA1LCAtMywgNCwgLTRdXSxcbiAgICBcIjxcIjogWzI0LCBbMjAsIDE4LCA0LCA5LCAyMCwgMF1dLFxuICAgIFwiPVwiOiBbMjYsIFs0LCAxMiwgMjIsIDEyLCAtMSwgLTEsIDQsIDYsIDIyLCA2XV0sXG4gICAgXCI+XCI6IFsyNCwgWzQsIDE4LCAyMCwgOSwgNCwgMF1dLFxuICAgIFwiP1wiOiBbMTgsIFszLCAxNiwgMywgMTcsIDQsIDE5LCA1LCAyMCwgNywgMjEsIDExLCAyMSwgMTMsIDIwLCAxNCwgMTksIDE1LCAxNywgMTUsIDE1LCAxNCwgMTMsIDEzLCAxMiwgOSwgMTAsIDksIDcsIC0xLCAtMSwgOSwgMiwgOCwgMSwgOSwgMCwgMTAsIDEsIDksIDJdXSxcbiAgICBcIkBcIjogWzI3LCBbMTgsIDEzLCAxNywgMTUsIDE1LCAxNiwgMTIsIDE2LCAxMCwgMTUsIDksIDE0LCA4LCAxMSwgOCwgOCwgOSwgNiwgMTEsIDUsIDE0LCA1LCAxNiwgNiwgMTcsIDgsIC0xLCAtMSwgMTIsIDE2LCAxMCwgMTQsIDksIDExLCA5LCA4LCAxMCwgNiwgMTEsIDUsIC0xLCAtMSwgMTgsIDE2LCAxNywgOCwgMTcsIDYsIDE5LCA1LCAyMSwgNSwgMjMsIDcsIDI0LCAxMCwgMjQsIDEyLCAyMywgMTUsIDIyLCAxNywgMjAsIDE5LCAxOCwgMjAsIDE1LCAyMSwgMTIsIDIxLCA5LCAyMCwgNywgMTksIDUsIDE3LCA0LCAxNSwgMywgMTIsIDMsIDksIDQsIDYsIDUsIDQsIDcsIDIsIDksIDEsIDEyLCAwLCAxNSwgMCwgMTgsIDEsIDIwLCAyLCAyMSwgMywgLTEsIC0xLCAxOSwgMTYsIDE4LCA4LCAxOCwgNiwgMTksIDVdXSxcbiAgICBcIkFcIjogWzE4LCBbOSwgMjEsIDEsIDAsIC0xLCAtMSwgOSwgMjEsIDE3LCAwLCAtMSwgLTEsIDQsIDcsIDE0LCA3XV0sXG4gICAgXCJCXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgLTEsIC0xLCA0LCAxMSwgMTMsIDExLCAxNiwgMTAsIDE3LCA5LCAxOCwgNywgMTgsIDQsIDE3LCAyLCAxNiwgMSwgMTMsIDAsIDQsIDBdXSxcbiAgICBcIkNcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1XV0sXG4gICAgXCJEXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMSwgMjEsIDE0LCAyMCwgMTYsIDE4LCAxNywgMTYsIDE4LCAxMywgMTgsIDgsIDE3LCA1LCAxNiwgMywgMTQsIDEsIDExLCAwLCA0LCAwXV0sXG4gICAgXCJFXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxNywgMjEsIC0xLCAtMSwgNCwgMTEsIDEyLCAxMSwgLTEsIC0xLCA0LCAwLCAxNywgMF1dLFxuICAgIFwiRlwiOiBbMTgsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTcsIDIxLCAtMSwgLTEsIDQsIDExLCAxMiwgMTFdXSxcbiAgICBcIkdcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOCwgOCwgLTEsIC0xLCAxMywgOCwgMTgsIDhdXSxcbiAgICBcIkhcIjogWzIyLCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMCwgLTEsIC0xLCA0LCAxMSwgMTgsIDExXV0sXG4gICAgXCJJXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIkpcIjogWzE2LCBbMTIsIDIxLCAxMiwgNSwgMTEsIDIsIDEwLCAxLCA4LCAwLCA2LCAwLCA0LCAxLCAzLCAyLCAyLCA1LCAyLCA3XV0sXG4gICAgXCJLXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDE4LCAyMSwgNCwgNywgLTEsIC0xLCA5LCAxMiwgMTgsIDBdXSxcbiAgICBcIkxcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMCwgMTYsIDBdXSxcbiAgICBcIk1cIjogWzI0LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMjEsIDEyLCAwLCAtMSwgLTEsIDIwLCAyMSwgMTIsIDAsIC0xLCAtMSwgMjAsIDIxLCAyMCwgMF1dLFxuICAgIFwiTlwiOiBbMjIsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTgsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMF1dLFxuICAgIFwiT1wiOiBbMjIsIFs5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOSwgOCwgMTksIDEzLCAxOCwgMTYsIDE3LCAxOCwgMTUsIDIwLCAxMywgMjEsIDksIDIxXV0sXG4gICAgXCJQXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNCwgMTcsIDEyLCAxNiwgMTEsIDEzLCAxMCwgNCwgMTBdXSxcbiAgICBcIlFcIjogWzIyLCBbOSwgMjEsIDcsIDIwLCA1LCAxOCwgNCwgMTYsIDMsIDEzLCAzLCA4LCA0LCA1LCA1LCAzLCA3LCAxLCA5LCAwLCAxMywgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNSwgMTksIDgsIDE5LCAxMywgMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgLTEsIC0xLCAxMiwgNCwgMTgsIC0yXV0sXG4gICAgXCJSXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgNCwgMTEsIC0xLCAtMSwgMTEsIDExLCAxOCwgMF1dLFxuICAgIFwiU1wiOiBbMjAsIFsxNywgMTgsIDE1LCAyMCwgMTIsIDIxLCA4LCAyMSwgNSwgMjAsIDMsIDE4LCAzLCAxNiwgNCwgMTQsIDUsIDEzLCA3LCAxMiwgMTMsIDEwLCAxNSwgOSwgMTYsIDgsIDE3LCA2LCAxNywgMywgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCAzLCAzXV0sXG4gICAgXCJUXCI6IFsxNiwgWzgsIDIxLCA4LCAwLCAtMSwgLTEsIDEsIDIxLCAxNSwgMjFdXSxcbiAgICBcIlVcIjogWzIyLCBbNCwgMjEsIDQsIDYsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMiwgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNiwgMTgsIDIxXV0sXG4gICAgXCJWXCI6IFsxOCwgWzEsIDIxLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMF1dLFxuICAgIFwiV1wiOiBbMjQsIFsyLCAyMSwgNywgMCwgLTEsIC0xLCAxMiwgMjEsIDcsIDAsIC0xLCAtMSwgMTIsIDIxLCAxNywgMCwgLTEsIC0xLCAyMiwgMjEsIDE3LCAwXV0sXG4gICAgXCJYXCI6IFsyMCwgWzMsIDIxLCAxNywgMCwgLTEsIC0xLCAxNywgMjEsIDMsIDBdXSxcbiAgICBcIllcIjogWzE4LCBbMSwgMjEsIDksIDExLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMTFdXSxcbiAgICBcIlpcIjogWzIwLCBbMTcsIDIxLCAzLCAwLCAtMSwgLTEsIDMsIDIxLCAxNywgMjEsIC0xLCAtMSwgMywgMCwgMTcsIDBdXSxcbiAgICBcIltcIjogWzE0LCBbNCwgMjUsIDQsIC03LCAtMSwgLTEsIDUsIDI1LCA1LCAtNywgLTEsIC0xLCA0LCAyNSwgMTEsIDI1LCAtMSwgLTEsIDQsIC03LCAxMSwgLTddXSxcbiAgICBcIlxcXFxcIjogWzE0LCBbMCwgMjEsIDE0LCAtM11dLFxuICAgIFwiXVwiOiBbMTQsIFs5LCAyNSwgOSwgLTcsIC0xLCAtMSwgMTAsIDI1LCAxMCwgLTcsIC0xLCAtMSwgMywgMjUsIDEwLCAyNSwgLTEsIC0xLCAzLCAtNywgMTAsIC03XV0sXG4gICAgXCJeXCI6IFsxNiwgWzYsIDE1LCA4LCAxOCwgMTAsIDE1LCAtMSwgLTEsIDMsIDEyLCA4LCAxNywgMTMsIDEyLCAtMSwgLTEsIDgsIDE3LCA4LCAwXV0sXG4gICAgXCJfXCI6IFsxNiwgWzAsIC0yLCAxNiwgLTJdXSxcbiAgICBcImBcIjogWzEwLCBbNiwgMjEsIDUsIDIwLCA0LCAxOCwgNCwgMTYsIDUsIDE1LCA2LCAxNiwgNSwgMTddXSxcbiAgICBcImFcIjogWzE5LCBbMTUsIDE0LCAxNSwgMCwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJiXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDExLCA2LCAxMywgOCwgMTQsIDExLCAxNCwgMTMsIDEzLCAxNSwgMTEsIDE2LCA4LCAxNiwgNiwgMTUsIDMsIDEzLCAxLCAxMSwgMCwgOCwgMCwgNiwgMSwgNCwgM11dLFxuICAgIFwiY1wiOiBbMTgsIFsxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJkXCI6IFsxOSwgWzE1LCAyMSwgMTUsIDAsIC0xLCAtMSwgMTUsIDExLCAxMywgMTMsIDExLCAxNCwgOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgM11dLFxuICAgIFwiZVwiOiBbMTgsIFszLCA4LCAxNSwgOCwgMTUsIDEwLCAxNCwgMTIsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJmXCI6IFsxMiwgWzEwLCAyMSwgOCwgMjEsIDYsIDIwLCA1LCAxNywgNSwgMCwgLTEsIC0xLCAyLCAxNCwgOSwgMTRdXSxcbiAgICBcImdcIjogWzE5LCBbMTUsIDE0LCAxNSwgLTIsIDE0LCAtNSwgMTMsIC02LCAxMSwgLTcsIDgsIC03LCA2LCAtNiwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJoXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDEwLCA3LCAxMywgOSwgMTQsIDEyLCAxNCwgMTQsIDEzLCAxNSwgMTAsIDE1LCAwXV0sXG4gICAgXCJpXCI6IFs4LCBbMywgMjEsIDQsIDIwLCA1LCAyMSwgNCwgMjIsIDMsIDIxLCAtMSwgLTEsIDQsIDE0LCA0LCAwXV0sXG4gICAgXCJqXCI6IFsxMCwgWzUsIDIxLCA2LCAyMCwgNywgMjEsIDYsIDIyLCA1LCAyMSwgLTEsIC0xLCA2LCAxNCwgNiwgLTMsIDUsIC02LCAzLCAtNywgMSwgLTddXSxcbiAgICBcImtcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTQsIDE0LCA0LCA0LCAtMSwgLTEsIDgsIDgsIDE1LCAwXV0sXG4gICAgXCJsXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIm1cIjogWzMwLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDAsIC0xLCAtMSwgMTUsIDEwLCAxOCwgMTMsIDIwLCAxNCwgMjMsIDE0LCAyNSwgMTMsIDI2LCAxMCwgMjYsIDBdXSxcbiAgICBcIm5cIjogWzE5LCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDBdXSxcbiAgICBcIm9cIjogWzE5LCBbOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgMywgMTYsIDYsIDE2LCA4LCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNF1dLFxuICAgIFwicFwiOiBbMTksIFs0LCAxNCwgNCwgLTcsIC0xLCAtMSwgNCwgMTEsIDYsIDEzLCA4LCAxNCwgMTEsIDE0LCAxMywgMTMsIDE1LCAxMSwgMTYsIDgsIDE2LCA2LCAxNSwgMywgMTMsIDEsIDExLCAwLCA4LCAwLCA2LCAxLCA0LCAzXV0sXG4gICAgXCJxXCI6IFsxOSwgWzE1LCAxNCwgMTUsIC03LCAtMSwgLTEsIDE1LCAxMSwgMTMsIDEzLCAxMSwgMTQsIDgsIDE0LCA2LCAxMywgNCwgMTEsIDMsIDgsIDMsIDYsIDQsIDMsIDYsIDEsIDgsIDAsIDExLCAwLCAxMywgMSwgMTUsIDNdXSxcbiAgICBcInJcIjogWzEzLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgOCwgNSwgMTEsIDcsIDEzLCA5LCAxNCwgMTIsIDE0XV0sXG4gICAgXCJzXCI6IFsxNywgWzE0LCAxMSwgMTMsIDEzLCAxMCwgMTQsIDcsIDE0LCA0LCAxMywgMywgMTEsIDQsIDksIDYsIDgsIDExLCA3LCAxMywgNiwgMTQsIDQsIDE0LCAzLCAxMywgMSwgMTAsIDAsIDcsIDAsIDQsIDEsIDMsIDNdXSxcbiAgICBcInRcIjogWzEyLCBbNSwgMjEsIDUsIDQsIDYsIDEsIDgsIDAsIDEwLCAwLCAtMSwgLTEsIDIsIDE0LCA5LCAxNF1dLFxuICAgIFwidVwiOiBbMTksIFs0LCAxNCwgNCwgNCwgNSwgMSwgNywgMCwgMTAsIDAsIDEyLCAxLCAxNSwgNCwgLTEsIC0xLCAxNSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ2XCI6IFsxNiwgWzIsIDE0LCA4LCAwLCAtMSwgLTEsIDE0LCAxNCwgOCwgMF1dLFxuICAgIFwid1wiOiBbMjIsIFszLCAxNCwgNywgMCwgLTEsIC0xLCAxMSwgMTQsIDcsIDAsIC0xLCAtMSwgMTEsIDE0LCAxNSwgMCwgLTEsIC0xLCAxOSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ4XCI6IFsxNywgWzMsIDE0LCAxNCwgMCwgLTEsIC0xLCAxNCwgMTQsIDMsIDBdXSxcbiAgICBcInlcIjogWzE2LCBbMiwgMTQsIDgsIDAsIC0xLCAtMSwgMTQsIDE0LCA4LCAwLCA2LCAtNCwgNCwgLTYsIDIsIC03LCAxLCAtN11dLFxuICAgIFwielwiOiBbMTcsIFsxNCwgMTQsIDMsIDAsIC0xLCAtMSwgMywgMTQsIDE0LCAxNCwgLTEsIC0xLCAzLCAwLCAxNCwgMF1dLFxuICAgIFwie1wiOiBbMTQsIFs5LCAyNSwgNywgMjQsIDYsIDIzLCA1LCAyMSwgNSwgMTksIDYsIDE3LCA3LCAxNiwgOCwgMTQsIDgsIDEyLCA2LCAxMCwgLTEsIC0xLCA3LCAyNCwgNiwgMjIsIDYsIDIwLCA3LCAxOCwgOCwgMTcsIDksIDE1LCA5LCAxMywgOCwgMTEsIDQsIDksIDgsIDcsIDksIDUsIDksIDMsIDgsIDEsIDcsIDAsIDYsIC0yLCA2LCAtNCwgNywgLTYsIC0xLCAtMSwgNiwgOCwgOCwgNiwgOCwgNCwgNywgMiwgNiwgMSwgNSwgLTEsIDUsIC0zLCA2LCAtNSwgNywgLTYsIDksIC03XV0sXG4gICAgXCJ8XCI6IFs4LCBbNCwgMjUsIDQsIC03XV0sXG4gICAgXCJ9XCI6IFsxNCwgWzUsIDI1LCA3LCAyNCwgOCwgMjMsIDksIDIxLCA5LCAxOSwgOCwgMTcsIDcsIDE2LCA2LCAxNCwgNiwgMTIsIDgsIDEwLCAtMSwgLTEsIDcsIDI0LCA4LCAyMiwgOCwgMjAsIDcsIDE4LCA2LCAxNywgNSwgMTUsIDUsIDEzLCA2LCAxMSwgMTAsIDksIDYsIDcsIDUsIDUsIDUsIDMsIDYsIDEsIDcsIDAsIDgsIC0yLCA4LCAtNCwgNywgLTYsIC0xLCAtMSwgOCwgOCwgNiwgNiwgNiwgNCwgNywgMiwgOCwgMSwgOSwgLTEsIDksIC0zLCA4LCAtNSwgNywgLTYsIDUsIC03XV0sXG4gICAgXCJ+XCI6IFsyNCwgWzMsIDYsIDMsIDgsIDQsIDExLCA2LCAxMiwgOCwgMTIsIDEwLCAxMSwgMTQsIDgsIDE2LCA3LCAxOCwgNywgMjAsIDgsIDIxLCAxMCwgLTEsIC0xLCAzLCA4LCA0LCAxMCwgNiwgMTEsIDgsIDExLCAxMCwgMTAsIDE0LCA3LCAxNiwgNiwgMTgsIDYsIDIwLCA3LCAyMSwgMTAsIDIxLCAxMl1dXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRleHRWZXJ0aWNlcyh0ZXh0LCBsZWZ0LCBiYXNlbGluZSwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDE7XG5cbiAgICB2YXIgc3Ryb2tlcyA9IFtdLFxuICAgICAgICBpLCBsZW4sIGosIGxlbjIsIGdseXBoLCB4LCB5LCBwcmV2O1xuXG4gICAgZm9yIChpID0gMCwgbGVuID0gdGV4dC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBnbHlwaCA9IHNpbXBsZXhGb250W3RleHRbaV1dO1xuICAgICAgICBpZiAoIWdseXBoKSBjb250aW51ZTtcbiAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgZm9yIChqID0gMCwgbGVuMiA9IGdseXBoWzFdLmxlbmd0aDsgaiA8IGxlbjI7IGogKz0gMikge1xuICAgICAgICAgICAgaWYgKGdseXBoWzFdW2pdID09PSAtMSAmJiBnbHlwaFsxXVtqICsgMV0gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeCA9IGxlZnQgKyBnbHlwaFsxXVtqXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIHkgPSBiYXNlbGluZSAtIGdseXBoWzFdW2ogKyAxXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZXMucHVzaChwcmV2LngsIHByZXYueSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXYgPSB7eDogeCwgeTogeX07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGVmdCArPSBnbHlwaFswXSAqIHNjYWxlO1xuICAgIH1cblxuICAgIHJldHVybiBzdHJva2VzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBtYXBib3hnbCBpcyBhIEEgV2ViR0wgSmF2YVNjcmlwdCBpbnRlcmFjdGl2ZSBtYXBzIGxpYnJhcnkgdGhhdCBjYW4gcmVuZGVyXG4gKiBbTWFwYm94IHZlY3RvciB0aWxlc10oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9ibG9nL3ZlY3Rvci10aWxlcy8pLlxuICpcbiAqIEBtb2R1bGUgbWFwYm94Z2xcbiAqIEBzdW1tYXJ5IFdlYkdMIEphdmFTY3JpcHQgbWFwIGxpYnJhcnlcbiAqL1xuXG4vLyBqc2hpbnQgLVcwNzlcbnZhciBtYXBib3hnbCA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbm1hcGJveGdsLk1hcCA9IHJlcXVpcmUoJy4vdWkvbWFwJyk7XG5tYXBib3hnbC5OYXZpZ2F0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL25hdmlnYXRpb24nKTtcbm1hcGJveGdsLkF0dHJpYnV0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL2F0dHJpYnV0aW9uJyk7XG5tYXBib3hnbC5Qb3B1cCA9IHJlcXVpcmUoJy4vdWkvcG9wdXAnKTtcblxubWFwYm94Z2wuR2VvSlNPTlNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL2dlb2pzb25fc291cmNlJyk7XG5tYXBib3hnbC5WaWRlb1NvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL3ZpZGVvX3NvdXJjZScpO1xuXG5tYXBib3hnbC5TdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUvc3R5bGUnKTtcblxubWFwYm94Z2wuTGF0TG5nID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZycpO1xubWFwYm94Z2wuTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbm1hcGJveGdsLlBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubWFwYm94Z2wuRXZlbnRlZCA9IHJlcXVpcmUoJy4vdXRpbC9ldmVudGVkJyk7XG5tYXBib3hnbC51dGlsID0gcmVxdWlyZSgnLi91dGlsL3V0aWwnKTtcblxubWFwYm94Z2wuc3VwcG9ydGVkID0gcmVxdWlyZSgnLi91dGlsL2Jyb3dzZXInKS5zdXBwb3J0ZWQ7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi91dGlsL2FqYXgnKTtcbm1hcGJveGdsLnV0aWwuZ2V0SlNPTiA9IGFqYXguZ2V0SlNPTjtcbm1hcGJveGdsLnV0aWwuZ2V0QXJyYXlCdWZmZXIgPSBhamF4LmdldEFycmF5QnVmZmVyO1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi91dGlsL2NvbmZpZycpO1xubWFwYm94Z2wuY29uZmlnID0gY29uZmlnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWFwYm94Z2wsICdhY2Nlc3NUb2tlbicsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnLkFDQ0VTU19UT0tFTjsgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHRva2VuKSB7IGNvbmZpZy5BQ0NFU1NfVE9LRU4gPSB0b2tlbjsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBtYXQzID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0MztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3QmFja2dyb3VuZDtcblxuZnVuY3Rpb24gZHJhd0JhY2tncm91bmQocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtY29sb3InXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnYmFja2dyb3VuZC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtb3BhY2l0eSddO1xuICAgIHZhciBzaGFkZXI7XG5cbiAgICB2YXIgaW1hZ2VQb3NBID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpIDogbnVsbDtcbiAgICB2YXIgaW1hZ2VQb3NCID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLnRvLCB0cnVlKSA6IG51bGw7XG5cbiAgICBpZiAoaW1hZ2VQb3NBICYmIGltYWdlUG9zQikge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZSwgMCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9hLCBpbWFnZVBvc0EudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYSwgaW1hZ2VQb3NBLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2IsIGltYWdlUG9zQi50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9iLCBpbWFnZVBvc0IuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eSwgb3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgICAgICB2YXIgc2l6ZUEgPSBpbWFnZVBvc0Euc2l6ZTtcbiAgICAgICAgdmFyIHNpemVCID0gaW1hZ2VQb3NCLnNpemU7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0cmFuc2Zvcm0ubG9jYXRpb25Db29yZGluYXRlKHRyYW5zZm9ybS5jZW50ZXIpO1xuICAgICAgICB2YXIgc2NhbGUgPSAxIC8gTWF0aC5wb3coMiwgdHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21peCwgaW1hZ2UudCk7XG5cbiAgICAgICAgdmFyIG1hdHJpeEEgPSBtYXQzLmNyZWF0ZSgpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIDEgLyAoc2l6ZUFbMF0gKiBpbWFnZS5mcm9tU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQVsxXSAqIGltYWdlLmZyb21TY2FsZSlcbiAgICAgICAgXSk7XG4gICAgICAgIG1hdDMudHJhbnNsYXRlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIChjZW50ZXIuY29sdW1uICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQVswXSAqIGltYWdlLmZyb21TY2FsZSksXG4gICAgICAgICAgICAoY2VudGVyLnJvdyAgICAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUFbMV0gKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhBLCBtYXRyaXhBLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICB2YXIgbWF0cml4QiA9IG1hdDMuY3JlYXRlKCk7XG4gICAgICAgIG1hdDMuc2NhbGUobWF0cml4QiwgbWF0cml4QiwgW1xuICAgICAgICAgICAgMSAvIChzaXplQlswXSAqIGltYWdlLnRvU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnRyYW5zbGF0ZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAoY2VudGVyLmNvbHVtbiAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUJbMF0gKiBpbWFnZS50b1NjYWxlKSxcbiAgICAgICAgICAgIChjZW50ZXIucm93ICAgICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhCLCBtYXRyaXhCLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYSwgZmFsc2UsIG1hdHJpeEEpO1xuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYiwgZmFsc2UsIG1hdHJpeEIpO1xuXG4gICAgICAgIHBhaW50ZXIuc3ByaXRlQXRsYXMuYmluZChnbCwgdHJ1ZSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEcmF3IGZpbGxpbmcgcmVjdGFuZ2xlLlxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmZpbGxTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm00ZnYoc2hhZGVyLnVfY29sb3IsIGNvbG9yKTtcbiAgICB9XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIuaXRlbUNvdW50KTtcbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcblxuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3UGxhY2VtZW50RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdQbGFjZW1lbnREZWJ1ZyhwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlKSB7XG5cbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdLmNvbGxpc2lvbkJveDtcbiAgICBpZiAoIWVsZW1lbnRHcm91cHMpIHJldHVybjtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGJ1ZmZlciA9IHRpbGUuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIHNoYWRlciA9IHBhaW50ZXIuY29sbGlzaW9uQm94U2hhZGVyO1xuXG4gICAgZ2wuZW5hYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgIGJ1ZmZlci5iaW5kKGdsLCBzaGFkZXIpO1xuICAgIGdsLmxpbmVXaWR0aCgzKTtcblxuICAgIHZhciBzdHJpZGUgPSAxMjtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZXh0cnVkZSwgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDQpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YSwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgOCk7XG5cbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2NhbGUsIE1hdGgucG93KDIsIHBhaW50ZXIudHJhbnNmb3JtLnpvb20gLSB0aWxlLmNvb3JkLnopKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfem9vbSwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWF4em9vbSwgKHRpbGUuY29vcmQueiArIDEpICogMTApO1xuXG4gICAgdmFyIGJlZ2luID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4U3RhcnRJbmRleDtcbiAgICB2YXIgbGVuID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4TGVuZ3RoO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIGJlZ2luLCBsZW4pO1xuXG4gICAgZ2wuZGlzYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdGV4dFZlcnRpY2VzID0gcmVxdWlyZSgnLi4vbGliL2RlYnVndGV4dCcpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdEZWJ1ZyhwYWludGVyLCB0aWxlKSB7XG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcblxuICAgIC8vIEJsZW5kIHRvIHRoZSBmcm9udCwgbm90IHRoZSBiYWNrLlxuICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZGVidWdTaGFkZXIsIHRpbGUucG9zTWF0cml4KTtcblxuICAgIC8vIGRyYXcgYm91bmRpbmcgcmVjdGFuZ2xlXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuZGVidWdCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z0J1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC51bmlmb3JtNGYocGFpbnRlci5kZWJ1Z1NoYWRlci51X2NvbG9yLCAxLCAwLCAwLCAxKTtcbiAgICBnbC5saW5lV2lkdGgoNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FX1NUUklQLCAwLCBwYWludGVyLmRlYnVnQnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICB2YXIgdmVydGljZXMgPSB0ZXh0VmVydGljZXModGlsZS5jb29yZC50b1N0cmluZygpLCA1MCwgMjAwLCA1KTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmRlYnVnVGV4dEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KHZlcnRpY2VzKSwgZ2wuU1RSRUFNX0RSQVcpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wubGluZVdpZHRoKDggKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDEsIDEsIDEpO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHZlcnRpY2VzLmxlbmd0aCAvIHBhaW50ZXIuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplKTtcbiAgICBnbC5saW5lV2lkdGgoMiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgZ2wudW5pZm9ybTRmKHBhaW50ZXIuZGVidWdTaGFkZXIudV9jb2xvciwgMCwgMCwgMCwgMSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdmVydGljZXMubGVuZ3RoIC8gcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0MyA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDM7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0ZpbGw7XG5cbmZ1bmN0aW9uIGRyYXdGaWxsKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpIHtcbiAgICAvLyBObyBkYXRhXG4gICAgaWYgKCF0aWxlLmJ1ZmZlcnMpIHJldHVybjtcbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdO1xuICAgIGlmICghZWxlbWVudEdyb3VwcykgcmV0dXJuO1xuXG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcbiAgICB2YXIgdHJhbnNsYXRlZFBvc01hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2ZpbGwtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydmaWxsLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgY29sb3IgPSBsYXllci5wYWludFsnZmlsbC1jb2xvciddO1xuXG4gICAgdmFyIHZlcnRleCwgZWxlbWVudHMsIGdyb3VwLCBjb3VudDtcblxuICAgIC8vIERyYXcgdGhlIHN0ZW5jaWwgbWFzay5cblxuICAgIC8vIFdlJ3JlIG9ubHkgZHJhd2luZyB0byB0aGUgZmlyc3Qgc2V2ZW4gYml0cyAoPT0gc3VwcG9ydCBhIG1heGltdW0gb2ZcbiAgICAvLyAxMjcgb3ZlcmxhcHBpbmcgcG9seWdvbnMgaW4gb25lIHBsYWNlIGJlZm9yZSB3ZSBnZXQgcmVuZGVyaW5nIGVycm9ycykuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgzRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIERyYXcgZnJvbnQgZmFjaW5nIHRyaWFuZ2xlcy4gV2hlcmV2ZXIgdGhlIDB4ODAgYml0IGlzIDEsIHdlIGFyZVxuICAgIC8vIGluY3JlYXNpbmcgdGhlIGxvd2VyIDcgYml0cyBieSBvbmUgaWYgdGhlIHRyaWFuZ2xlIGlzIGEgZnJvbnQtZmFjaW5nXG4gICAgLy8gdHJpYW5nbGUuIFRoaXMgbWVhbnMgdGhhdCBhbGwgdmlzaWJsZSBwb2x5Z29ucyBzaG91bGQgYmUgaW4gQ0NXXG4gICAgLy8gb3JpZW50YXRpb24sIHdoaWxlIGFsbCBob2xlcyAoc2VlIGJlbG93KSBhcmUgaW4gQ1cgb3JpZW50YXRpb24uXG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuTk9URVFVQUwsIDB4ODAsIDB4ODApO1xuXG4gICAgLy8gV2hlbiB3ZSBkbyBhIG5vbnplcm8gZmlsbCwgd2UgY291bnQgdGhlIG51bWJlciBvZiB0aW1lcyBhIHBpeGVsIGlzXG4gICAgLy8gY292ZXJlZCBieSBhIGNvdW50ZXJjbG9ja3dpc2UgcG9seWdvbiwgYW5kIHN1YnRyYWN0IHRoZSBudW1iZXIgb2ZcbiAgICAvLyB0aW1lcyBpdCBpcyBcInVuY292ZXJlZFwiIGJ5IGEgY2xvY2t3aXNlIHBvbHlnb24uXG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuRlJPTlQsIGdsLklOQ1JfV1JBUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuQkFDSywgZ2wuREVDUl9XUkFQLCBnbC5LRUVQLCBnbC5LRUVQKTtcblxuICAgIC8vIFdoZW4gZHJhd2luZyBhIHNoYXBlLCB3ZSBmaXJzdCBkcmF3IGFsbCBzaGFwZXMgdG8gdGhlIHN0ZW5jaWwgYnVmZmVyXG4gICAgLy8gYW5kIGluY3JlbWVudGluZyBhbGwgYXJlYXMgd2hlcmUgcG9seWdvbnMgYXJlXG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIERyYXcgdGhlIGFjdHVhbCB0cmlhbmdsZSBmYW4gaW50byB0aGUgc3RlbmNpbCBidWZmZXIuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZmlsbFNoYWRlciwgdHJhbnNsYXRlZFBvc01hdHJpeCk7XG5cbiAgICAvLyBEcmF3IGFsbCBidWZmZXJzXG4gICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIGVsZW1lbnRzLmJpbmQoZ2wpO1xuXG4gICAgdmFyIG9mZnNldCwgZWxlbWVudE9mZnNldDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmZpbGxTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgNCwgb2Zmc2V0ICsgMCk7XG5cbiAgICAgICAgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgc3RlbmNpbCBtYXNrIGluIHRoZSBzdGVuY2lsIGJ1ZmZlciwgd2UgY2FuIHN0YXJ0XG4gICAgLy8gd3JpdGluZyB0byB0aGUgY29sb3IgYnVmZmVyLlxuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcblxuICAgIC8vIEZyb20gbm93IG9uLCB3ZSBkb24ndCB3YW50IHRvIHVwZGF0ZSB0aGUgc3RlbmNpbCBidWZmZXIgYW55bW9yZS5cbiAgICBnbC5zdGVuY2lsT3AoZ2wuS0VFUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwKTtcblxuICAgIHZhciBzdHJva2VDb2xvciA9IGxheWVyLnBhaW50WydmaWxsLW91dGxpbmUtY29sb3InXTtcblxuICAgIC8vIEJlY2F1c2Ugd2UncmUgZHJhd2luZyB0b3AtdG8tYm90dG9tLCBhbmQgd2UgdXBkYXRlIHRoZSBzdGVuY2lsIG1hc2tcbiAgICAvLyBiZWxvdywgd2UgaGF2ZSB0byBkcmF3IHRoZSBvdXRsaW5lIGZpcnN0ICghKVxuICAgIGlmIChsYXllci5wYWludFsnZmlsbC1hbnRpYWxpYXMnXSA9PT0gdHJ1ZSAmJiAhKGxheWVyLnBhaW50WydmaWxsLWltYWdlJ10gJiYgIXN0cm9rZUNvbG9yKSkge1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLCB0cmFuc2xhdGVkUG9zTWF0cml4KTtcbiAgICAgICAgZ2wubGluZVdpZHRoKDIgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuXG4gICAgICAgIGlmIChzdHJva2VDb2xvcikge1xuICAgICAgICAgICAgLy8gSWYgd2UgZGVmaW5lZCBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGZpbGwgb3V0bGluZSwgd2UgYXJlXG4gICAgICAgICAgICAvLyBnb2luZyB0byBpZ25vcmUgdGhlIGJpdHMgaW4gMHgzRiBhbmQganVzdCBjYXJlIGFib3V0IHRoZSBnbG9iYWxcbiAgICAgICAgICAgIC8vIGNsaXBwaW5nIG1hc2suXG4gICAgICAgICAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIG9ubHkgd2FudCB0byBkcmF3IHRoZSBhbnRpYWxpYXNlZCBwYXJ0cyB0aGF0IGFyZVxuICAgICAgICAgICAgLy8gKm91dHNpZGUqIHRoZSBjdXJyZW50IHNoYXBlLiBUaGlzIGlzIGltcG9ydGFudCBpbiBjYXNlIHRoZSBmaWxsXG4gICAgICAgICAgICAvLyBvciBzdHJva2UgY29sb3IgaXMgdHJhbnNsdWNlbnQuIElmIHdlIHdvdWxkbid0IGNsaXAgdG8gb3V0c2lkZVxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2hhcGUsIHNvbWUgcGl4ZWxzIGZyb20gdGhlIG91dGxpbmUgc3Ryb2tlIG92ZXJsYXBwZWRcbiAgICAgICAgICAgIC8vIHRoZSAobm9uLWFudGlhbGlhc2VkKSBmaWxsLlxuICAgICAgICAgICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4QkYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmKHBhaW50ZXIub3V0bGluZVNoYWRlci51X3dvcmxkLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHBhaW50ZXIub3V0bGluZVNoYWRlci51X2NvbG9yLCBzdHJva2VDb2xvciA/IHN0cm9rZUNvbG9yIDogY29sb3IpO1xuXG4gICAgICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICAgICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLm91dGxpbmVFbGVtZW50O1xuICAgICAgICBlbGVtZW50cy5iaW5kKGdsKTtcblxuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDQsIG9mZnNldCArIDApO1xuXG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGggKiAyO1xuICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICBnbC5kcmF3RWxlbWVudHMoZ2wuTElORVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnZmlsbC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2ZpbGwtb3BhY2l0eSddIHx8IDE7XG4gICAgdmFyIHNoYWRlcjtcblxuICAgIGlmIChpbWFnZSkge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICB2YXIgaW1hZ2VQb3NBID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS5mcm9tLCB0cnVlKTtcbiAgICAgICAgdmFyIGltYWdlUG9zQiA9IHBhaW50ZXIuc3ByaXRlQXRsYXMuZ2V0UG9zaXRpb24oaW1hZ2UudG8sIHRydWUpO1xuICAgICAgICBpZiAoIWltYWdlUG9zQSB8fCAhaW1hZ2VQb3NCKSByZXR1cm47XG5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5wYXR0ZXJuU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtMWkoc2hhZGVyLnVfaW1hZ2UsIDApO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYSwgaW1hZ2VQb3NBLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2EsIGltYWdlUG9zQS5icik7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9iLCBpbWFnZVBvc0IudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYiwgaW1hZ2VQb3NCLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIG9wYWNpdHkpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBpbWFnZS50KTtcblxuICAgICAgICB2YXIgZmFjdG9yID0gKHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUpIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gLSB0aWxlLmNvb3JkLnopO1xuXG4gICAgICAgIHZhciBtYXRyaXhBID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQS5zaXplWzBdICogZmFjdG9yICogaW1hZ2UuZnJvbVNjYWxlKSxcbiAgICAgICAgICAgIDEgLyAoaW1hZ2VQb3NBLnNpemVbMV0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHZhciBtYXRyaXhCID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzBdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSksXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzFdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSlcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2EsIGZhbHNlLCBtYXRyaXhBKTtcbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2IsIGZhbHNlLCBtYXRyaXhCKTtcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRHJhdyBmaWxsaW5nIHJlY3RhbmdsZS5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5maWxsU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgLy8gT25seSBkcmF3IHJlZ2lvbnMgdGhhdCB3ZSBtYXJrZWRcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHgwLCAweDNGKTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4ODApO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDIgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQyO1xuXG4vKipcbiAqIERyYXcgYSBsaW5lLiBVbmRlciB0aGUgaG9vZCB0aGlzIHdpbGwgcmVhZCBlbGVtZW50cyBmcm9tXG4gKiBhIHRpbGUsIGRhc2ggdGV4dHVyZXMgZnJvbSBhIGxpbmVBdGxhcywgYW5kIHN0eWxlIHByb3BlcnRpZXMgZnJvbSBhIGxheWVyLlxuICogQHBhcmFtIHtPYmplY3R9IHBhaW50ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXllclxuICogQHBhcmFtIHtPYmplY3R9IHBvc01hdHJpeFxuICogQHBhcmFtIHtUaWxlfSB0aWxlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBkcmF3cyB3aXRoIHRoZSBwYWludGVyXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhd0xpbmUocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuXG4gICAgLy8gZG9uJ3QgZHJhdyB6ZXJvLXdpZHRoIGxpbmVzXG4gICAgaWYgKGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ10gPD0gMCkgcmV0dXJuO1xuXG4gICAgLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXG4gICAgLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXG4gICAgdmFyIGFudGlhbGlhc2luZyA9IDEgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICB2YXIgYmx1ciA9IGxheWVyLnBhaW50WydsaW5lLWJsdXInXSArIGFudGlhbGlhc2luZztcbiAgICB2YXIgZWRnZVdpZHRoID0gbGF5ZXIucGFpbnRbJ2xpbmUtd2lkdGgnXSAvIDI7XG4gICAgdmFyIGluc2V0ID0gLTE7XG4gICAgdmFyIG9mZnNldCA9IDA7XG4gICAgdmFyIHNoaWZ0ID0gMDtcblxuICAgIGlmIChsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSA+IDApIHtcbiAgICAgICAgaW5zZXQgPSBsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSAvIDIgKyBhbnRpYWxpYXNpbmcgKiAwLjU7XG4gICAgICAgIGVkZ2VXaWR0aCA9IGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ107XG5cbiAgICAgICAgLy8gc2hpZnQgb3V0ZXIgbGluZXMgaGFsZiBhIHBpeGVsIHRvd2FyZHMgdGhlIG1pZGRsZSB0byBlbGltaW5hdGUgdGhlIGNyYWNrXG4gICAgICAgIG9mZnNldCA9IGluc2V0IC0gYW50aWFsaWFzaW5nIC8gMjtcbiAgICB9XG5cbiAgICB2YXIgb3V0c2V0ID0gb2Zmc2V0ICsgZWRnZVdpZHRoICsgYW50aWFsaWFzaW5nIC8gMiArIHNoaWZ0O1xuXG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2xpbmUtY29sb3InXTtcbiAgICB2YXIgcmF0aW8gPSBwYWludGVyLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHZ0eE1hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2xpbmUtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydsaW5lLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgdHIgPSBwYWludGVyLnRyYW5zZm9ybTtcblxuXG4gICAgdmFyIGFudGlhbGlhc2luZ01hdHJpeCA9IG1hdDIuY3JlYXRlKCk7XG4gICAgbWF0Mi5zY2FsZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgWzEsIE1hdGguY29zKHRyLl9waXRjaCldKTtcbiAgICBtYXQyLnJvdGF0ZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgcGFpbnRlci50cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIGxvbmdlciB0aGUgcmVhbCB3b3JsZCBkaXN0YW5jZSBpcyBhdCB0aGUgdG9wIG9mIHRoZSBzY3JlZW5cbiAgICAvLyB0aGFuIGF0IHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbi5cbiAgICB2YXIgdG9wZWRnZWxlbmd0aCA9IE1hdGguc3FydCh0ci5oZWlnaHQgKiB0ci5oZWlnaHQgLyA0ICAqICgxICsgdHIuYWx0aXR1ZGUgKiB0ci5hbHRpdHVkZSkpO1xuICAgIHZhciB4ID0gdHIuaGVpZ2h0IC8gMiAqIE1hdGgudGFuKHRyLl9waXRjaCk7XG4gICAgdmFyIGV4dHJhID0gKHRvcGVkZ2VsZW5ndGggKyB4KSAvIHRvcGVkZ2VsZW5ndGggLSAxO1xuXG4gICAgLy8gaG93IG11Y2ggdGhlIHRpbGUgaXMgb3ZlcnNjYWxlZCBieVxuICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUudGlsZVNpemUgLyBwYWludGVyLnRyYW5zZm9ybS50aWxlU2l6ZTtcblxuICAgIHZhciBzaGFkZXI7XG5cblxuICAgIHZhciBkYXNoYXJyYXkgPSBsYXllci5wYWludFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnbGluZS1pbWFnZSddO1xuXG4gICAgaWYgKGRhc2hhcnJheSkge1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXNkZnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgY29sb3IpO1xuXG4gICAgICAgIHZhciBwb3NBID0gcGFpbnRlci5saW5lQXRsYXMuZ2V0RGFzaChkYXNoYXJyYXkuZnJvbSwgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgdmFyIHBvc0IgPSBwYWludGVyLmxpbmVBdGxhcy5nZXREYXNoKGRhc2hhcnJheS50bywgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgcGFpbnRlci5saW5lQXRsYXMuYmluZChnbCk7XG5cbiAgICAgICAgdmFyIHBhdHRlcm5yYXRpbyA9IE1hdGgucG93KDIsIE1hdGguZmxvb3IoTWF0aC5sb2cocGFpbnRlci50cmFuc2Zvcm0uc2NhbGUpIC8gTWF0aC5MTjIpIC0gdGlsZS5jb29yZC56KSAvIDggKiBvdmVyc2NhbGluZztcbiAgICAgICAgdmFyIHNjYWxlQSA9IFtwYXR0ZXJucmF0aW8gLyBwb3NBLndpZHRoIC8gZGFzaGFycmF5LmZyb21TY2FsZSwgLXBvc0EuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUEgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkuZnJvbVNjYWxlICogcG9zQS53aWR0aCAqIDI1NiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbykgLyAyO1xuICAgICAgICB2YXIgc2NhbGVCID0gW3BhdHRlcm5yYXRpbyAvIHBvc0Iud2lkdGggLyBkYXNoYXJyYXkudG9TY2FsZSwgLXBvc0IuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUIgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkudG9TY2FsZSAqIHBvc0Iud2lkdGggKiAyNTYgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pIC8gMjtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5zY2FsZV9hLCBzY2FsZUEpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfdGV4X3lfYSwgcG9zQS55KTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuc2NhbGVfYiwgc2NhbGVCKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3RleF95X2IsIHBvc0IueSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlLCAwKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NkZmdhbW1hLCBNYXRoLm1heChnYW1tYUEsIGdhbW1hQikpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBkYXNoYXJyYXkudCk7XG5cbiAgICB9IGVsc2UgaWYgKGltYWdlKSB7XG4gICAgICAgIHZhciBpbWFnZVBvc0EgPSBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpO1xuICAgICAgICB2YXIgaW1hZ2VQb3NCID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS50bywgdHJ1ZSk7XG4gICAgICAgIGlmICghaW1hZ2VQb3NBIHx8ICFpbWFnZVBvc0IpIHJldHVybjtcbiAgICAgICAgdmFyIGZhY3RvciA9IHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUgLyBNYXRoLnBvdygyLCBwYWludGVyLnRyYW5zZm9ybS50aWxlWm9vbSAtIHRpbGUuY29vcmQueikgKiBvdmVyc2NhbGluZztcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9hLCBbaW1hZ2VQb3NBLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUsIGltYWdlUG9zQi5zaXplWzFdIF0pO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9iLCBbaW1hZ2VQb3NCLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS50b1NjYWxlLCBpbWFnZVBvc0Iuc2l6ZVsxXSBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2EsIGltYWdlUG9zQS50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9hLCBpbWFnZVBvc0EuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYiwgaW1hZ2VQb3NCLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2IsIGltYWdlUG9zQi5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlLCBpbWFnZS50KTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIGxheWVyLnBhaW50WydsaW5lLW9wYWNpdHknXSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmxpbmVTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2V4dHJhLCBleHRyYSk7XG4gICAgICAgIGdsLnVuaWZvcm1NYXRyaXgyZnYoc2hhZGVyLnVfYW50aWFsaWFzaW5nbWF0cml4LCBmYWxzZSwgYW50aWFsaWFzaW5nTWF0cml4KTtcblxuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgdmFyIHZlcnRleCA9IHRpbGUuYnVmZmVycy5saW5lVmVydGV4O1xuICAgIHZlcnRleC5iaW5kKGdsKTtcbiAgICB2YXIgZWxlbWVudCA9IHRpbGUuYnVmZmVycy5saW5lRWxlbWVudDtcbiAgICBlbGVtZW50LmJpbmQoZ2wpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50R3JvdXBzLmdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHZ0eE9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIHZ0eE9mZnNldCArIDApO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGEsIDQsIGdsLkJZVEUsIGZhbHNlLCA4LCB2dHhPZmZzZXQgKyA0KTtcblxuICAgICAgICB2YXIgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgdmFyIGVsZW1lbnRPZmZzZXQgPSBncm91cC5lbGVtZW50U3RhcnRJbmRleCAqIGVsZW1lbnQuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdSYXN0ZXI7XG5cbmZ1bmN0aW9uIGRyYXdSYXN0ZXIocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICB2YXIgc2hhZGVyID0gcGFpbnRlci5yYXN0ZXJTaGFkZXI7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4KTtcblxuICAgIC8vIGNvbG9yIHBhcmFtZXRlcnNcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnJpZ2h0bmVzc19sb3csIGxheWVyLnBhaW50WydyYXN0ZXItYnJpZ2h0bmVzcy1taW4nXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2JyaWdodG5lc3NfaGlnaCwgbGF5ZXIucGFpbnRbJ3Jhc3Rlci1icmlnaHRuZXNzLW1heCddKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2F0dXJhdGlvbl9mYWN0b3IsIHNhdHVyYXRpb25GYWN0b3IobGF5ZXIucGFpbnRbJ3Jhc3Rlci1zYXR1cmF0aW9uJ10pKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfY29udHJhc3RfZmFjdG9yLCBjb250cmFzdEZhY3RvcihsYXllci5wYWludFsncmFzdGVyLWNvbnRyYXN0J10pKTtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlci51X3NwaW5fd2VpZ2h0cywgc3BpbldlaWdodHMobGF5ZXIucGFpbnRbJ3Jhc3Rlci1odWUtcm90YXRlJ10pKTtcblxuICAgIHZhciBwYXJlbnRUaWxlID0gdGlsZS5zb3VyY2UgJiYgdGlsZS5zb3VyY2UuX3B5cmFtaWQuZmluZExvYWRlZFBhcmVudCh0aWxlLmNvb3JkLCAwLCB7fSksXG4gICAgICAgIG9wYWNpdGllcyA9IGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgcGFpbnRlci50cmFuc2Zvcm0pO1xuXG4gICAgdmFyIHBhcmVudFNjYWxlQnksIHBhcmVudFRMO1xuXG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcblxuICAgIGlmIChwYXJlbnRUaWxlKSB7XG4gICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTEpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBwYXJlbnRUaWxlLnRleHR1cmUpO1xuXG4gICAgICAgIHBhcmVudFNjYWxlQnkgPSBNYXRoLnBvdygyLCBwYXJlbnRUaWxlLmNvb3JkLnogLSB0aWxlLmNvb3JkLnopO1xuICAgICAgICBwYXJlbnRUTCA9IFt0aWxlLmNvb3JkLnggKiBwYXJlbnRTY2FsZUJ5ICUgMSwgdGlsZS5jb29yZC55ICogcGFyZW50U2NhbGVCeSAlIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wYWNpdGllc1sxXSA9IDA7XG4gICAgfVxuXG4gICAgLy8gY3Jvc3MtZmFkZSBwYXJhbWV0ZXJzXG4gICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV90bF9wYXJlbnQsIHBhcmVudFRMIHx8IFswLCAwXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NjYWxlX3BhcmVudCwgcGFyZW50U2NhbGVCeSB8fCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyX3NjYWxlLCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eTAsIG9wYWNpdGllc1swXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHkxLCBvcGFjaXRpZXNbMV0pO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTAsIDApO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTEsIDEpO1xuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRpbGUuYm91bmRzQnVmZmVyIHx8IHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlcik7XG5cbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgICAgICAgICAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfdGV4dHVyZV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgOCwgNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbn1cblxuZnVuY3Rpb24gc3BpbldlaWdodHMoYW5nbGUpIHtcbiAgICBhbmdsZSAqPSBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBzID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIHZhciBjID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHJldHVybiBbXG4gICAgICAgICgyICogYyArIDEpIC8gMyxcbiAgICAgICAgKC1NYXRoLnNxcnQoMykgKiBzIC0gYyArIDEpIC8gMyxcbiAgICAgICAgKE1hdGguc3FydCgzKSAqIHMgLSBjICsgMSkgLyAzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY29udHJhc3RGYWN0b3IoY29udHJhc3QpIHtcbiAgICByZXR1cm4gY29udHJhc3QgPiAwID9cbiAgICAgICAgMSAvICgxIC0gY29udHJhc3QpIDpcbiAgICAgICAgMSArIGNvbnRyYXN0O1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0aW9uRmFjdG9yKHNhdHVyYXRpb24pIHtcbiAgICByZXR1cm4gc2F0dXJhdGlvbiA+IDAgP1xuICAgICAgICAxIC0gMSAvICgxLjAwMSAtIHNhdHVyYXRpb24pIDpcbiAgICAgICAgLXNhdHVyYXRpb247XG59XG5cbmZ1bmN0aW9uIGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgdHJhbnNmb3JtKSB7XG4gICAgaWYgKCF0aWxlLnNvdXJjZSkgcmV0dXJuIFsxLCAwXTtcblxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIHZhciBmYWRlRHVyYXRpb24gPSBsYXllci5wYWludFsncmFzdGVyLWZhZGUtZHVyYXRpb24nXTtcbiAgICB2YXIgc2luY2VUaWxlID0gKG5vdyAtIHRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbjtcbiAgICB2YXIgc2luY2VQYXJlbnQgPSBwYXJlbnRUaWxlID8gKG5vdyAtIHBhcmVudFRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbiA6IC0xO1xuXG4gICAgdmFyIGlkZWFsWiA9IHRpbGUuc291cmNlLl9weXJhbWlkLmNvdmVyaW5nWm9vbUxldmVsKHRyYW5zZm9ybSk7XG4gICAgdmFyIHBhcmVudEZ1cnRoZXIgPSBwYXJlbnRUaWxlID8gTWF0aC5hYnMocGFyZW50VGlsZS5jb29yZC56IC0gaWRlYWxaKSA+IE1hdGguYWJzKHRpbGUuY29vcmQueiAtIGlkZWFsWikgOiBmYWxzZTtcblxuICAgIHZhciBvcGFjaXR5ID0gW107XG4gICAgaWYgKCFwYXJlbnRUaWxlIHx8IHBhcmVudEZ1cnRoZXIpIHtcbiAgICAgICAgLy8gaWYgbm8gcGFyZW50IG9yIHBhcmVudCBpcyBvbGRlclxuICAgICAgICBvcGFjaXR5WzBdID0gdXRpbC5jbGFtcChzaW5jZVRpbGUsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIHlvdW5nZXIsIHpvb21pbmcgb3V0XG4gICAgICAgIG9wYWNpdHlbMF0gPSB1dGlsLmNsYW1wKDEgLSBzaW5jZVBhcmVudCwgMCwgMSk7XG4gICAgICAgIG9wYWNpdHlbMV0gPSAxIC0gb3BhY2l0eVswXTtcbiAgICB9XG5cbiAgICB2YXIgb3AgPSBsYXllci5wYWludFsncmFzdGVyLW9wYWNpdHknXTtcbiAgICBvcGFjaXR5WzBdICo9IG9wO1xuICAgIG9wYWNpdHlbMV0gKj0gb3A7XG5cbiAgICByZXR1cm4gb3BhY2l0eTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBtYXQ0ID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0NDtcblxudmFyIGRyYXdDb2xsaXNpb25EZWJ1ZyA9IHJlcXVpcmUoJy4vZHJhd19jb2xsaXNpb25fZGVidWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3U3ltYm9scztcblxuZnVuY3Rpb24gZHJhd1N5bWJvbHMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZHJhd0Fjcm9zc0VkZ2VzID0gIShsYXllci5sYXlvdXRbJ3RleHQtYWxsb3ctb3ZlcmxhcCddIHx8IGxheWVyLmxheW91dFsnaWNvbi1hbGxvdy1vdmVybGFwJ10gfHxcbiAgICAgICAgbGF5ZXIubGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXllci5sYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKTtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoZHJhd0Fjcm9zc0VkZ2VzKSB7XG4gICAgICAgIC8vIERpc2FibGUgdGhlIHN0ZW5jaWwgdGVzdCBzbyB0aGF0IGxhYmVscyBhcmVuJ3QgY2xpcHBlZCB0byB0aWxlIGJvdW5kYXJpZXMuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIExheWVycyB3aXRoIGZlYXR1cmVzIHRoYXQgbWF5IGJlIGRyYXduIG92ZXJsYXBwaW5nIGFyZW4ndCBjbGlwcGVkLiBUaGVzZVxuICAgICAgICAvLyBsYXllcnMgYXJlIHNvcnRlZCBpbiB0aGUgeSBkaXJlY3Rpb24sIGFuZCB0byBkcmF3IHRoZSBjb3JyZWN0IG9yZGVyaW5nIG5lYXJcbiAgICAgICAgLy8gdGlsZSBlZGdlcyB0aGUgaWNvbnMgYXJlIGluY2x1ZGVkIGluIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgd2hlbiBkcmF3aW5nLlxuICAgICAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRHcm91cHMudGV4dC5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2wocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSwgZWxlbWVudEdyb3Vwcy50ZXh0LCAndGV4dCcsIHRydWUpO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudEdyb3Vwcy5pY29uLmdyb3Vwcy5sZW5ndGgpIHtcbiAgICAgICAgZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLmljb24sICdpY29uJywgZWxlbWVudEdyb3Vwcy5zZGZJY29ucyk7XG4gICAgfVxuXG4gICAgZHJhd0NvbGxpc2lvbkRlYnVnKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKGRyYXdBY3Jvc3NFZGdlcykge1xuICAgICAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0U2l6ZXMgPSB7XG4gICAgaWNvbjogMSxcbiAgICB0ZXh0OiAyNFxufTtcblxuZnVuY3Rpb24gZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLCBwcmVmaXgsIHNkZikge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBwb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHRpbGUsIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlLWFuY2hvciddKTtcblxuICAgIHZhciB0ciA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgIHZhciBhbGlnbmVkV2l0aE1hcCA9IGxheWVyLmxheW91dFtwcmVmaXggKyAnLXJvdGF0aW9uLWFsaWdubWVudCddID09PSAnbWFwJztcbiAgICB2YXIgc2tld2VkID0gYWxpZ25lZFdpdGhNYXA7XG4gICAgdmFyIGV4TWF0cml4LCBzLCBnYW1tYVNjYWxlO1xuXG4gICAgaWYgKHNrZXdlZCkge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIHMgPSB0aWxlLnRpbGVFeHRlbnQgLyB0aWxlLnRpbGVTaXplIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAtIHRpbGUuY29vcmQueik7XG4gICAgICAgIGdhbW1hU2NhbGUgPSAxIC8gTWF0aC5jb3ModHIuX3BpdGNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY2xvbmUodGlsZS5leE1hdHJpeCk7XG4gICAgICAgIHMgPSBwYWludGVyLnRyYW5zZm9ybS5hbHRpdHVkZTtcbiAgICAgICAgZ2FtbWFTY2FsZSA9IDE7XG4gICAgfVxuICAgIG1hdDQuc2NhbGUoZXhNYXRyaXgsIGV4TWF0cml4LCBbcywgcywgMV0pO1xuXG4gICAgLy8gSWYgbGF5ZXIucGFpbnQuc2l6ZSA+IGxheWVyLmxheW91dFtwcmVmaXggKyAnLW1heC1zaXplJ10gdGhlbiBsYWJlbHMgbWF5IGNvbGxpZGVcbiAgICB2YXIgZm9udFNpemUgPSBsYXllci5wYWludFtwcmVmaXggKyAnLXNpemUnXTtcbiAgICB2YXIgZm9udFNjYWxlID0gZm9udFNpemUgLyBkZWZhdWx0U2l6ZXNbcHJlZml4XTtcbiAgICBtYXQ0LnNjYWxlKGV4TWF0cml4LCBleE1hdHJpeCwgWyBmb250U2NhbGUsIGZvbnRTY2FsZSwgMSBdKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBob3cgbXVjaCBsb25nZXIgdGhlIHJlYWwgd29ybGQgZGlzdGFuY2UgaXMgYXQgdGhlIHRvcCBvZiB0aGUgc2NyZWVuXG4gICAgLy8gdGhhbiBhdCB0aGUgbWlkZGxlIG9mIHRoZSBzY3JlZW4uXG4gICAgdmFyIHRvcGVkZ2VsZW5ndGggPSBNYXRoLnNxcnQodHIuaGVpZ2h0ICogdHIuaGVpZ2h0IC8gNCAgKiAoMSArIHRyLmFsdGl0dWRlICogdHIuYWx0aXR1ZGUpKTtcbiAgICB2YXIgeCA9IHRyLmhlaWdodCAvIDIgKiBNYXRoLnRhbih0ci5fcGl0Y2gpO1xuICAgIHZhciBleHRyYSA9ICh0b3BlZGdlbGVuZ3RoICsgeCkgLyB0b3BlZGdlbGVuZ3RoIC0gMTtcblxuICAgIHZhciB0ZXh0ID0gcHJlZml4ID09PSAndGV4dCc7XG4gICAgdmFyIHNoYWRlciwgdmVydGV4LCBlbGVtZW50cywgdGV4c2l6ZTtcblxuICAgIGlmICghdGV4dCAmJiAhcGFpbnRlci5zdHlsZS5zcHJpdGUubG9hZGVkKCkpXG4gICAgICAgIHJldHVybjtcblxuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgaWYgKHNkZikge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnNkZlNoYWRlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmljb25TaGFkZXI7XG4gICAgfVxuXG4gICAgaWYgKHRleHQpIHtcbiAgICAgICAgcGFpbnRlci5nbHlwaEF0bGFzLnVwZGF0ZVRleHR1cmUoZ2wpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmdseXBoRWxlbWVudDtcbiAgICAgICAgdGV4c2l6ZSA9IFtwYWludGVyLmdseXBoQXRsYXMud2lkdGggLyA0LCBwYWludGVyLmdseXBoQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcGFpbnRlci5zcHJpdGVBdGxhcy5iaW5kKGdsLCBhbGlnbmVkV2l0aE1hcCB8fCBwYWludGVyLm9wdGlvbnMucm90YXRpbmcgfHxcbiAgICAgICAgICAgIHBhaW50ZXIub3B0aW9ucy56b29taW5nIHx8IGZvbnRTY2FsZSAhPT0gMSB8fCBzZGYgfHwgcGFpbnRlci50cmFuc2Zvcm0ucGl0Y2gpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgZWxlbWVudHMgPSB0aWxlLmJ1ZmZlcnMuaWNvbkVsZW1lbnQ7XG4gICAgICAgIHRleHNpemUgPSBbcGFpbnRlci5zcHJpdGVBdGxhcy53aWR0aCAvIDQsIHBhaW50ZXIuc3ByaXRlQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfVxuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3RleHR1cmUsIDApO1xuICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfdGV4c2l6ZSwgdGV4c2l6ZSk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3NrZXdlZCwgc2tld2VkKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZXh0cmEsIGV4dHJhKTtcblxuICAgIC8vIGFkanVzdCBtaW4vbWF4IHpvb21zIGZvciB2YXJpYWJsZSBmb250IHNpZXNcbiAgICB2YXIgem9vbUFkanVzdCA9IE1hdGgubG9nKGZvbnRTaXplIC8gbGF5ZXIubGF5b3V0W3ByZWZpeCArICctbWF4LXNpemUnXSkgLyBNYXRoLkxOMiB8fCAwO1xuXG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3pvb20sIChwYWludGVyLnRyYW5zZm9ybS56b29tIC0gem9vbUFkanVzdCkgKiAxMCk7IC8vIGN1cnJlbnQgem9vbSBsZXZlbFxuXG4gICAgdmFyIGYgPSBwYWludGVyLmZyYW1lSGlzdG9yeS5nZXRGYWRlUHJvcGVydGllcygzMDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlZGlzdCwgZi5mYWRlZGlzdCAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWluZmFkZXpvb20sIE1hdGguZmxvb3IoZi5taW5mYWRlem9vbSAqIDEwKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21heGZhZGV6b29tLCBNYXRoLmZsb29yKGYubWF4ZmFkZXpvb20gKiAxMCkpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlem9vbSwgKHBhaW50ZXIudHJhbnNmb3JtLnpvb20gKyBmLmJ1bXApICogMTApO1xuXG4gICAgdmFyIGdyb3VwLCBvZmZzZXQsIGNvdW50LCBlbGVtZW50T2Zmc2V0O1xuXG4gICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICBpZiAoc2RmKSB7XG4gICAgICAgIHZhciBzZGZQeCA9IDg7XG4gICAgICAgIHZhciBibHVyT2Zmc2V0ID0gMS4xOTtcbiAgICAgICAgdmFyIGhhbG9PZmZzZXQgPSA2O1xuICAgICAgICB2YXIgZ2FtbWEgPSAwLjEwNSAqIGRlZmF1bHRTaXplc1twcmVmaXhdIC8gZm9udFNpemUgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCBnYW1tYSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBsYXllci5wYWludFtwcmVmaXggKyAnLWNvbG9yJ10pO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyLCAoMjU2IC0gNjQpIC8gMjU2KTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2ldO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pIHtcbiAgICAgICAgICAgIC8vIERyYXcgaGFsbyB1bmRlcm5lYXRoIHRoZSB0ZXh0LlxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWJsdXInXSAqIGJsdXJPZmZzZXQgLyBmb250U2NhbGUgLyBzZGZQeCArIGdhbW1hKSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgbGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKGhhbG9PZmZzZXQgLSBsYXllci5wYWludFtwcmVmaXggKyAnLWhhbG8td2lkdGgnXSAvIGZvbnRTY2FsZSkgLyBzZGZQeCk7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2pdO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgdmVydGV4LmJpbmQoZ2wsIHNoYWRlciwgb2Zmc2V0KTtcblxuICAgICAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBsYXllci5wYWludFsnaWNvbi1vcGFjaXR5J10pO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd1ZlcnRpY2VzO1xuXG5mdW5jdGlvbiBkcmF3VmVydGljZXMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoIXRpbGUgfHwgIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICBpZiAobGF5ZXIudHlwZSA9PT0gJ2ZpbGwnKSB7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXgsIGVsZW1lbnRHcm91cHMuZ3JvdXBzLCBwb3NNYXRyaXgsIDQpO1xuICAgIH0gZWxzZSBpZiAobGF5ZXIudHlwZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleCwgZWxlbWVudEdyb3Vwcy5pY29uLmdyb3VwcywgcG9zTWF0cml4LCAxNik7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmdseXBoVmVydGV4LCBlbGVtZW50R3JvdXBzLnRleHQuZ3JvdXBzLCBwb3NNYXRyaXgsIDE2KTtcbiAgICB9IGVsc2UgaWYgKGxheWVyLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgICB2YXIgbmV3UG9zTWF0cml4ID0gbWF0NC5jbG9uZShwb3NNYXRyaXgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG5ld1Bvc01hdHJpeCwgbmV3UG9zTWF0cml4LCBbMC41LCAwLjUsIDFdKTtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMubGluZVZlcnRleCwgZWxlbWVudEdyb3Vwcy5ncm91cHMsIG5ld1Bvc01hdHJpeCwgOCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1BvaW50cyh2ZXJ0ZXgsIGdyb3VwcywgbWF0cml4LCBzdHJpZGUpIHtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZG90U2hhZGVyLCBtYXRyaXgpO1xuXG4gICAgICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X3NpemUsIDQgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICBnbC51bmlmb3JtMWYocGFpbnRlci5kb3RTaGFkZXIudV9ibHVyLCAwLjI1KTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihwYWludGVyLmRvdFNoYWRlci51X2NvbG9yLCBbMC4xLCAwLCAwLCAwLjFdKTtcblxuICAgICAgICB2ZXJ0ZXguYmluZChnbCwgcGFpbnRlci5kb3RTaGFkZXIsIDApO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldO1xuICAgICAgICAgICAgdmFyIGJlZ2luID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgICAgIHZhciBjb3VudCA9IGdyb3VwLnZlcnRleExlbmd0aDtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kb3RTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCAwKTtcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCBiZWdpbiwgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gRnJhbWVIaXN0b3J5O1xuXG5mdW5jdGlvbiBGcmFtZUhpc3RvcnkoKSB7XG4gICAgdGhpcy5mcmFtZUhpc3RvcnkgPSBbXTtcbn1cblxuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5nZXRGYWRlUHJvcGVydGllcyA9IGZ1bmN0aW9uKGR1cmF0aW9uKSB7XG4gICAgaWYgKGR1cmF0aW9uID09PSB1bmRlZmluZWQpIGR1cmF0aW9uID0gMzAwO1xuICAgIHZhciBjdXJyZW50VGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBSZW1vdmUgZnJhbWVzIHVudGlsIG9ubHkgb25lIGlzIG91dHNpZGUgdGhlIGR1cmF0aW9uLCBvciB1bnRpbCB0aGVyZSBhcmUgb25seSB0aHJlZVxuICAgIHdoaWxlICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPiAzICYmIHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5LnNoaWZ0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5WzBdLnogPSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56O1xuICAgIH1cblxuICAgIHZhciBmcmFtZUxlbiA9IHRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aDtcbiAgICBpZiAoZnJhbWVMZW4gPCAzKSBjb25zb2xlLndhcm4oJ3RoZXJlIHNob3VsZCBuZXZlciBiZSBsZXNzIHRoYW4gdGhyZWUgZnJhbWVzIGluIHRoZSBoaXN0b3J5Jyk7XG5cbiAgICAvLyBGaW5kIHRoZSByYW5nZSBvZiB6b29tIGxldmVscyB3ZSB3YW50IHRvIGZhZGUgYmV0d2VlblxuICAgIHZhciBzdGFydGluZ1ogPSB0aGlzLmZyYW1lSGlzdG9yeVswXS56LFxuICAgICAgICBsYXN0RnJhbWUgPSB0aGlzLmZyYW1lSGlzdG9yeVtmcmFtZUxlbiAtIDFdLFxuICAgICAgICBlbmRpbmdaID0gbGFzdEZyYW1lLnosXG4gICAgICAgIGxvd1ogPSBNYXRoLm1pbihzdGFydGluZ1osIGVuZGluZ1opLFxuICAgICAgICBoaWdoWiA9IE1hdGgubWF4KHN0YXJ0aW5nWiwgZW5kaW5nWik7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHNwZWVkIG9mIHpvb21pbmcsIGFuZCBob3cgZmFyIGl0IHdvdWxkIHpvb20gaW4gdGVybXMgb2Ygem9vbSBsZXZlbHMgaW4gb25lIGR1cmF0aW9uXG4gICAgdmFyIHpvb21EaWZmID0gbGFzdEZyYW1lLnogLSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56LFxuICAgICAgICB0aW1lRGlmZiA9IGxhc3RGcmFtZS50aW1lIC0gdGhpcy5mcmFtZUhpc3RvcnlbMV0udGltZTtcbiAgICB2YXIgZmFkZWRpc3QgPSB6b29tRGlmZiAvICh0aW1lRGlmZiAvIGR1cmF0aW9uKTtcblxuICAgIGlmIChpc05hTihmYWRlZGlzdCkpIGNvbnNvbGUud2FybignZmFkZWRpc3Qgc2hvdWxkIG5ldmVyIGJlIE5hTicpO1xuXG4gICAgLy8gQXQgZW5kIG9mIGEgem9vbSB3aGVuIHRoZSB6b29tIHN0b3BzIGNoYW5naW5nIGNvbnRpbnVlIHByZXRlbmRpbmcgdG8gem9vbSBhdCB0aGF0IHNwZWVkXG4gICAgLy8gYnVtcCBpcyBob3cgbXVjaCBmYXJ0aGVyIGl0IHdvdWxkIGhhdmUgYmVlbiBpZiBpdCBoYWQgY29udGludWVkIHpvb21pbmcgYXQgdGhlIHNhbWUgcmF0ZVxuICAgIHZhciBidW1wID0gKGN1cnJlbnRUaW1lIC0gbGFzdEZyYW1lLnRpbWUpIC8gZHVyYXRpb24gKiBmYWRlZGlzdDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhZGVkaXN0OiBmYWRlZGlzdCxcbiAgICAgICAgbWluZmFkZXpvb206IGxvd1osXG4gICAgICAgIG1heGZhZGV6b29tOiBoaWdoWixcbiAgICAgICAgYnVtcDogYnVtcFxuICAgIH07XG59O1xuXG4vLyBSZWNvcmQgZnJhbWUgaGlzdG9yeSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYWxjdWxhdGUgZmFkaW5nIHBhcmFtc1xuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5yZWNvcmQgPSBmdW5jdGlvbih6b29tKSB7XG4gICAgdmFyIGN1cnJlbnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuICAgIC8vIGZpcnN0IGZyYW1lIGV2ZXJcbiAgICBpZiAoIXRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aCkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHt0aW1lOiAwLCB6OiB6b29tIH0sIHt0aW1lOiAwLCB6OiB6b29tIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPT09IDIgfHwgdGhpcy5mcmFtZUhpc3RvcnlbdGhpcy5mcmFtZUhpc3RvcnkubGVuZ3RoIC0gMV0ueiAhPT0gem9vbSkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHtcbiAgICAgICAgICAgIHRpbWU6IGN1cnJlbnRUaW1lLFxuICAgICAgICAgICAgejogem9vbVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxuZXhwb3J0cy5leHRlbmQgPSBmdW5jdGlvbihjb250ZXh0KSB7XG4gICAgdmFyIG9yaWdMaW5lV2lkdGggPSBjb250ZXh0LmxpbmVXaWR0aCxcbiAgICAgICAgbGluZVdpZHRoUmFuZ2UgPSBjb250ZXh0LmdldFBhcmFtZXRlcihjb250ZXh0LkFMSUFTRURfTElORV9XSURUSF9SQU5HRSk7XG5cbiAgICBjb250ZXh0LmxpbmVXaWR0aCA9IGZ1bmN0aW9uKHdpZHRoKSB7XG4gICAgICAgIG9yaWdMaW5lV2lkdGguY2FsbChjb250ZXh0LCB1dGlsLmNsYW1wKHdpZHRoLCBsaW5lV2lkdGhSYW5nZVswXSwgbGluZVdpZHRoUmFuZ2VbMV0pKTtcbiAgICB9O1xuXG4gICAgY29udGV4dC5nZXRTaGFkZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlKSB7XG4gICAgICAgIHZhciBraW5kID0gdHlwZSA9PT0gdGhpcy5GUkFHTUVOVF9TSEFERVIgPyAnZnJhZ21lbnQnIDogJ3ZlcnRleCc7XG4gICAgICAgIGlmICghc2hhZGVyc1tuYW1lXSB8fCAhc2hhZGVyc1tuYW1lXVtraW5kXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgc2hhZGVyIFwiICsgbmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hhZGVyID0gdGhpcy5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgIHRoaXMuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyc1tuYW1lXVtraW5kXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICBpZiAoIXRoaXMuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgdGhpcy5DT01QSUxFX1NUQVRVUykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNoYWRlcjtcbiAgICB9O1xuXG4gICAgY29udGV4dC5pbml0aWFsaXplU2hhZGVyID0gZnVuY3Rpb24obmFtZSwgYXR0cmlidXRlcywgdW5pZm9ybXMpIHtcbiAgICAgICAgdmFyIHNoYWRlciA9IHtcbiAgICAgICAgICAgIHByb2dyYW06IHRoaXMuY3JlYXRlUHJvZ3JhbSgpLFxuICAgICAgICAgICAgZnJhZ21lbnQ6IHRoaXMuZ2V0U2hhZGVyKG5hbWUsIHRoaXMuRlJBR01FTlRfU0hBREVSKSxcbiAgICAgICAgICAgIHZlcnRleDogdGhpcy5nZXRTaGFkZXIobmFtZSwgdGhpcy5WRVJURVhfU0hBREVSKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYXR0YWNoU2hhZGVyKHNoYWRlci5wcm9ncmFtLCBzaGFkZXIudmVydGV4KTtcbiAgICAgICAgdGhpcy5hdHRhY2hTaGFkZXIoc2hhZGVyLnByb2dyYW0sIHNoYWRlci5mcmFnbWVudCk7XG4gICAgICAgIHRoaXMubGlua1Byb2dyYW0oc2hhZGVyLnByb2dyYW0pO1xuXG4gICAgICAgIGlmICghdGhpcy5nZXRQcm9ncmFtUGFyYW1ldGVyKHNoYWRlci5wcm9ncmFtLCB0aGlzLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLmdldFByb2dyYW1JbmZvTG9nKHNoYWRlci5wcm9ncmFtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJbYXR0cmlidXRlc1tpXV0gPSB0aGlzLmdldEF0dHJpYkxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCBhdHRyaWJ1dGVzW2ldKTtcbiAgICAgICAgICAgICAgICBzaGFkZXIuYXR0cmlidXRlcy5wdXNoKHNoYWRlclthdHRyaWJ1dGVzW2ldXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHVuaWZvcm1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgc2hhZGVyW3VuaWZvcm1zW2tdXSA9IHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCB1bmlmb3Jtc1trXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH07XG5cbiAgICAvLyBTd2l0Y2hlcyB0byBhIGRpZmZlcmVudCBzaGFkZXIgcHJvZ3JhbS5cbiAgICBjb250ZXh0LnN3aXRjaFNoYWRlciA9IGZ1bmN0aW9uKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCkge1xuICAgICAgICBpZiAoIXBvc01hdHJpeCkge1xuICAgICAgICAgICAgY29uc29sZS50cmFjZSgncG9zTWF0cml4IGRvZXMgbm90IGhhdmUgcmVxdWlyZWQgYXJndW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTaGFkZXIgIT09IHNoYWRlcikge1xuICAgICAgICAgICAgdGhpcy51c2VQcm9ncmFtKHNoYWRlci5wcm9ncmFtKTtcblxuICAgICAgICAgICAgLy8gRGlzYWJsZSBhbGwgYXR0cmlidXRlcyBmcm9tIHRoZSBleGlzdGluZyBzaGFkZXIgdGhhdCBhcmVuJ3QgdXNlZCBpblxuICAgICAgICAgICAgLy8gdGhlIG5ldyBzaGFkZXIuIE5vdGU6IGF0dHJpYnV0ZSBpbmRpY2VzIGFyZSAqbm90KiBwcm9ncmFtIHNwZWNpZmljIVxuICAgICAgICAgICAgdmFyIGVuYWJsZWQgPSB0aGlzLmN1cnJlbnRTaGFkZXIgPyB0aGlzLmN1cnJlbnRTaGFkZXIuYXR0cmlidXRlcyA6IFtdO1xuICAgICAgICAgICAgdmFyIHJlcXVpcmVkID0gc2hhZGVyLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW5hYmxlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlZC5pbmRleE9mKGVuYWJsZWRbaV0pIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShlbmFibGVkW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVuYWJsZSBhbGwgYXR0cmlidXRlcyBmb3IgdGhlIG5ldyBzaGFkZXIuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlcXVpcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVuYWJsZWQuaW5kZXhPZihyZXF1aXJlZFtqXSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkocmVxdWlyZWRbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U2hhZGVyID0gc2hhZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtYXRyaWNlcyBpZiBuZWNlc3NhcnkuIE5vdGU6IFRoaXMgcmVsaWVzIG9uIG9iamVjdCBpZGVudGl0eSFcbiAgICAgICAgLy8gVGhpcyBtZWFucyBjaGFuZ2luZyB0aGUgbWF0cml4IHZhbHVlcyB3aXRob3V0IHRoZSBhY3R1YWwgbWF0cml4IG9iamVjdFxuICAgICAgICAvLyB3aWxsIEZBSUwgdG8gdXBkYXRlIHRoZSBtYXRyaXggcHJvcGVybHkuXG4gICAgICAgIGlmIChzaGFkZXIucG9zTWF0cml4ICE9PSBwb3NNYXRyaXgpIHtcbiAgICAgICAgICAgIHRoaXMudW5pZm9ybU1hdHJpeDRmdihzaGFkZXIudV9tYXRyaXgsIGZhbHNlLCBwb3NNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLnBvc01hdHJpeCA9IHBvc01hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhNYXRyaXggJiYgc2hhZGVyLmV4TWF0cml4ICE9PSBleE1hdHJpeCAmJiBzaGFkZXIudV9leG1hdHJpeCkge1xuICAgICAgICAgICAgdGhpcy51bmlmb3JtTWF0cml4NGZ2KHNoYWRlci51X2V4bWF0cml4LCBmYWxzZSwgZXhNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLmV4TWF0cml4ID0gZXhNYXRyaXg7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVBdGxhcztcblxuLyoqXG4gKiBNdWNoIGxpa2UgYSBHbHlwaEF0bGFzLCBhIExpbmVBdGxhcyBsZXRzIHVzIHJldXNlIHJlbmRlcmVkIGRhc2hlZCBsaW5lc1xuICogYnkgd3JpdGluZyBtYW55IG9mIHRoZW0gdG8gYSB0ZXh0dXJlIGFuZCB0aGVuIGZldGNoaW5nIHRoZWlyIHBvc2l0aW9uc1xuICogdXNpbmcgLmdldERhc2guXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBMaW5lQXRsYXMod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLm5leHRSb3cgPSAwO1xuXG4gICAgdGhpcy5ieXRlcyA9IDQ7XG4gICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy53aWR0aCAqIHRoaXMuaGVpZ2h0ICogdGhpcy5ieXRlcyk7XG5cbiAgICB0aGlzLnBvc2l0aW9ucyA9IHt9O1xufVxuXG5MaW5lQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuLyoqXG4gKiBHZXQgb3IgY3JlYXRlIGEgZGFzaCBsaW5lIHBhdHRlcm4uXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBkYXNoYXJyYXlcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gcm91bmQgd2hldGhlciB0byBhZGQgY2lyY2xlIGNhcHMgaW4gYmV0d2VlbiBkYXNoIHNlZ21lbnRzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwb3NpdGlvbiBvZiBkYXNoIHRleHR1cmUgaW4geyB5LCBoZWlnaHQsIHdpZHRoIH1cbiAqIEBwcml2YXRlXG4gKi9cbkxpbmVBdGxhcy5wcm90b3R5cGUuZ2V0RGFzaCA9IGZ1bmN0aW9uKGRhc2hhcnJheSwgcm91bmQpIHtcbiAgICB2YXIga2V5ID0gZGFzaGFycmF5LmpvaW4oXCIsXCIpICsgcm91bmQ7XG5cbiAgICBpZiAoIXRoaXMucG9zaXRpb25zW2tleV0pIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbnNba2V5XSA9IHRoaXMuYWRkRGFzaChkYXNoYXJyYXksIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucG9zaXRpb25zW2tleV07XG59O1xuXG5MaW5lQXRsYXMucHJvdG90eXBlLmFkZERhc2ggPSBmdW5jdGlvbihkYXNoYXJyYXksIHJvdW5kKSB7XG5cbiAgICB2YXIgbiA9IHJvdW5kID8gNyA6IDA7XG4gICAgdmFyIGhlaWdodCA9IDIgKiBuICsgMTtcbiAgICB2YXIgb2Zmc2V0ID0gMTI4O1xuXG4gICAgaWYgKHRoaXMubmV4dFJvdyArIGhlaWdodCA+IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTGluZUF0bGFzIG91dCBvZiBzcGFjZScpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhc2hhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZW5ndGggKz0gZGFzaGFycmF5W2ldO1xuICAgIH1cblxuICAgIHZhciBzdHJldGNoID0gdGhpcy53aWR0aCAvIGxlbmd0aDtcbiAgICB2YXIgaGFsZldpZHRoID0gc3RyZXRjaCAvIDI7XG5cbiAgICAvLyBJZiBkYXNoYXJyYXkgaGFzIGFuIG9kZCBsZW5ndGgsIGJvdGggdGhlIGZpcnN0IGFuZCBsYXN0IHBhcnRzXG4gICAgLy8gYXJlIGRhc2hlcyBhbmQgc2hvdWxkIGJlIGpvaW5lZCBzZWFtbGVzc2x5LlxuICAgIHZhciBvZGRMZW5ndGggPSBkYXNoYXJyYXkubGVuZ3RoICUgMiA9PT0gMTtcblxuICAgIGZvciAodmFyIHkgPSAtbjsgeSA8PSBuOyB5KyspIHtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMubmV4dFJvdyArIG4gKyB5O1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLndpZHRoICogcm93O1xuXG4gICAgICAgIHZhciBsZWZ0ID0gb2RkTGVuZ3RoID8gLWRhc2hhcnJheVtkYXNoYXJyYXkubGVuZ3RoIC0gMV0gOiAwO1xuICAgICAgICB2YXIgcmlnaHQgPSBkYXNoYXJyYXlbMF07XG4gICAgICAgIHZhciBwYXJ0SW5kZXggPSAxO1xuXG4gICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgdGhpcy53aWR0aDsgeCsrKSB7XG5cbiAgICAgICAgICAgIHdoaWxlIChyaWdodCA8IHggLyBzdHJldGNoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQgKyBkYXNoYXJyYXlbcGFydEluZGV4XTtcblxuICAgICAgICAgICAgICAgIGlmIChvZGRMZW5ndGggJiYgcGFydEluZGV4ID09PSBkYXNoYXJyYXkubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICByaWdodCArPSBkYXNoYXJyYXlbMF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcGFydEluZGV4Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBkaXN0TGVmdCA9IE1hdGguYWJzKHggLSBsZWZ0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdFJpZ2h0ID0gTWF0aC5hYnMoeCAtIHJpZ2h0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdCA9IE1hdGgubWluKGRpc3RMZWZ0LCBkaXN0UmlnaHQpO1xuICAgICAgICAgICAgdmFyIGluc2lkZSA9IChwYXJ0SW5kZXggJSAyKSA9PT0gMTtcbiAgICAgICAgICAgIHZhciBzaWduZWREaXN0YW5jZTtcblxuICAgICAgICAgICAgaWYgKHJvdW5kKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGNpcmNsZSBjYXBzXG4gICAgICAgICAgICAgICAgdmFyIGRpc3RNaWRkbGUgPSBuID8geSAvIG4gKiAoaGFsZldpZHRoICsgMSkgOiAwO1xuICAgICAgICAgICAgICAgIGlmIChpbnNpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RFZGdlID0gaGFsZldpZHRoIC0gTWF0aC5hYnMoZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgICAgIHNpZ25lZERpc3RhbmNlID0gTWF0aC5zcXJ0KGRpc3QgKiBkaXN0ICsgZGlzdEVkZ2UgKiBkaXN0RWRnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2lnbmVkRGlzdGFuY2UgPSBoYWxmV2lkdGggLSBNYXRoLnNxcnQoZGlzdCAqIGRpc3QgKyBkaXN0TWlkZGxlICogZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduZWREaXN0YW5jZSA9IChpbnNpZGUgPyAxIDogLTEpICogZGlzdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5kYXRhWzMgKyAoaW5kZXggKyB4KSAqIDRdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBzaWduZWREaXN0YW5jZSArIG9mZnNldCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHtcbiAgICAgICAgeTogKHRoaXMubmV4dFJvdyArIG4gKyAwLjUpIC8gdGhpcy5oZWlnaHQsXG4gICAgICAgIGhlaWdodDogMiAqIG4gLyB0aGlzLmhlaWdodCxcbiAgICAgICAgd2lkdGg6IGxlbmd0aFxuICAgIH07XG5cbiAgICB0aGlzLm5leHRSb3cgKz0gaGVpZ2h0O1xuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHBvcztcbn07XG5cbkxpbmVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHRoaXMuZGF0YSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuXG4gICAgICAgIGlmICh0aGlzLmRpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLmRhdGEpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuTGluZUF0bGFzLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIGNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgY2FudmFzLnN0eWxlLnRvcCA9IDA7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAwO1xuICAgIGNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kID0gJyNmZjAnO1xuXG4gICAgY2FudmFzLndpZHRoID0gdGhpcy53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdmFyIGRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5zZGYpIHtcbiAgICAgICAgICAgIHZhciBrID0gaSAqIDQ7XG4gICAgICAgICAgICBkYXRhLmRhdGFba10gPSBkYXRhLmRhdGFbayArIDFdID0gZGF0YS5kYXRhW2sgKyAyXSA9IDA7XG4gICAgICAgICAgICBkYXRhLmRhdGFbayArIDNdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0YS5kYXRhW2ldID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5wdXRJbWFnZURhdGEoZGF0YSwgMCwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2x1dGlsID0gcmVxdWlyZSgnLi9nbF91dGlsJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDQgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQ0O1xudmFyIEZyYW1lSGlzdG9yeSA9IHJlcXVpcmUoJy4vZnJhbWVfaGlzdG9yeScpO1xuXG4vKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBwYWludGVyIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0NhbnZhc30gZ2wgYW4gZXhwZXJpbWVudGFsLXdlYmdsIGRyYXdpbmcgY29udGV4dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IFBhaW50ZXI7XG5mdW5jdGlvbiBQYWludGVyKGdsLCB0cmFuc2Zvcm0pIHtcbiAgICB0aGlzLmdsID0gZ2x1dGlsLmV4dGVuZChnbCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5cbiAgICB0aGlzLnJldXNhYmxlVGV4dHVyZXMgPSB7fTtcbiAgICB0aGlzLnByZUZib3MgPSB7fTtcblxuICAgIHRoaXMuZnJhbWVIaXN0b3J5ID0gbmV3IEZyYW1lSGlzdG9yeSgpO1xuXG4gICAgdGhpcy5zZXR1cCgpO1xufVxuXG4vKlxuICogVXBkYXRlIHRoZSBHTCB2aWV3cG9ydCwgcHJvamVjdGlvbiBtYXRyaXgsIGFuZCB0cmFuc2Zvcm1zIHRvIGNvbXBlbnNhdGVcbiAqIGZvciBhIG5ldyB3aWR0aCBhbmQgaGVpZ2h0IHZhbHVlLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcblxuICAgIHRoaXMud2lkdGggPSB3aWR0aCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICBnbC52aWV3cG9ydCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cbn07XG5cblxuUGFpbnRlci5wcm90b3R5cGUuc2V0dXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgZ2wudmVyYm9zZSA9IHRydWU7XG5cbiAgICAvLyBXZSBhcmUgYmxlbmRpbmcgdGhlIG5ldyBwaXhlbHMgKmJlaGluZCogdGhlIGV4aXN0aW5nIHBpeGVscy4gVGhhdCB3YXkgd2UgY2FuXG4gICAgLy8gZHJhdyBmcm9udC10by1iYWNrIGFuZCB1c2UgdGhlbiBzdGVuY2lsIGJ1ZmZlciB0byBjdWxsIG9wYXF1ZSBwaXhlbHMgZWFybHkuXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKTtcbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FX01JTlVTX0RTVF9BTFBIQSwgZ2wuT05FKTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFkZXJzXG4gICAgdGhpcy5kZWJ1Z1NoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2RlYnVnJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfcG9pbnRzaXplJywgJ3VfY29sb3InXSk7XG5cbiAgICB0aGlzLmdhdXNzaWFuU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZ2F1c3NpYW4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9pbWFnZScsICd1X29mZnNldCddKTtcblxuICAgIHRoaXMucmFzdGVyU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcigncmFzdGVyJyxcbiAgICAgICAgWydhX3BvcycsICdhX3RleHR1cmVfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9icmlnaHRuZXNzX2xvdycsICd1X2JyaWdodG5lc3NfaGlnaCcsICd1X3NhdHVyYXRpb25fZmFjdG9yJywgJ3Vfc3Bpbl93ZWlnaHRzJywgJ3VfY29udHJhc3RfZmFjdG9yJywgJ3Vfb3BhY2l0eTAnLCAndV9vcGFjaXR5MScsICd1X2ltYWdlMCcsICd1X2ltYWdlMScsICd1X3RsX3BhcmVudCcsICd1X3NjYWxlX3BhcmVudCcsICd1X2J1ZmZlcl9zY2FsZSddKTtcblxuICAgIHRoaXMubGluZVNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2xpbmUnLFxuICAgICAgICBbJ2FfcG9zJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfbGluZXdpZHRoJywgJ3VfY29sb3InLCAndV9yYXRpbycsICd1X2JsdXInLCAndV9leHRyYScsICd1X2FudGlhbGlhc2luZ21hdHJpeCddKTtcblxuICAgIHRoaXMubGluZXBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X3JhdGlvJywgJ3VfcGF0dGVybl9zaXplX2EnLCAndV9wYXR0ZXJuX3NpemVfYicsICd1X3BhdHRlcm5fdGxfYScsICd1X3BhdHRlcm5fYnJfYScsICd1X3BhdHRlcm5fdGxfYicsICd1X3BhdHRlcm5fYnJfYicsICd1X2JsdXInLCAndV9mYWRlJywgJ3Vfb3BhY2l0eSddKTtcblxuICAgIHRoaXMubGluZXNkZnBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lc2RmcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X2NvbG9yJywgJ3VfcmF0aW8nLCAndV9ibHVyJywgJ3VfcGF0dGVybnNjYWxlX2EnLCAndV90ZXhfeV9hJywgJ3VfcGF0dGVybnNjYWxlX2InLCAndV90ZXhfeV9iJywgJ3VfaW1hZ2UnLCAndV9zZGZnYW1tYScsICd1X21peCddKTtcblxuICAgIHRoaXMuZG90U2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZG90JyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2l6ZScsICd1X2NvbG9yJywgJ3VfYmx1ciddKTtcblxuICAgIHRoaXMuc2RmU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignc2RmJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV9jb2xvcicsICd1X2dhbW1hJywgJ3VfYnVmZmVyJywgJ3Vfem9vbScsICd1X2ZhZGVkaXN0JywgJ3VfbWluZmFkZXpvb20nLCAndV9tYXhmYWRlem9vbScsICd1X2ZhZGV6b29tJywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLmljb25TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdpY29uJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV96b29tJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nLCAndV9vcGFjaXR5JywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLm91dGxpbmVTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdvdXRsaW5lJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InLCAndV93b3JsZCddXG4gICAgKTtcblxuICAgIHRoaXMucGF0dGVyblNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ3BhdHRlcm4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9wYXR0ZXJuX3RsX2EnLCAndV9wYXR0ZXJuX2JyX2EnLCAndV9wYXR0ZXJuX3RsX2InLCAndV9wYXR0ZXJuX2JyX2InLCAndV9taXgnLCAndV9wYXR0ZXJubWF0cml4X2EnLCAndV9wYXR0ZXJubWF0cml4X2InLCAndV9vcGFjaXR5JywgJ3VfaW1hZ2UnXVxuICAgICk7XG5cbiAgICB0aGlzLmZpbGxTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdmaWxsJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InXVxuICAgICk7XG5cbiAgICB0aGlzLmNvbGxpc2lvbkJveFNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2NvbGxpc2lvbmJveCcsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9leHRydWRlJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2NhbGUnLCAndV96b29tJywgJ3VfbWF4em9vbSddXG4gICAgKTtcblxuICAgIHRoaXMuaWRlbnRpdHlNYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuXG4gICAgLy8gVGhlIGJhY2tncm91bmRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gdGhlIGZ1bGwgKmNhbnZhcypcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUgPSAyO1xuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQgPSA0O1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCBuZXcgSW50MTZBcnJheShbLTEsIC0xLCAxLCAtMSwgLTEsIDEsIDEsIDFdKSwgZ2wuU1RBVElDX0RSQVcpO1xuXG4gICAgdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG5cbiAgICAvLyBUaGUgZGVidWdUZXh0QnVmZmVyIGlzIHVzZWQgdG8gZHJhdyB0aWxlIElEcyBmb3IgZGVidWdnaW5nXG4gICAgdGhpcy5kZWJ1Z1RleHRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnVGV4dEJ1ZmZlci5pdGVtU2l6ZSA9IDI7XG59O1xuXG4vKipcbiAqIFJlYmluZCB0aGUgbmVjZXNzYXJ5IGJ1ZmZlcnMgdG8gcmVuZGVyIGF0IGEgZGlmZmVyZW50IGV4dGVudCB0aGFuXG4gKiB0aGUgY3VycmVudCBvbmUuIE5vLW9wcyBpZiB0aGUgZXh0ZW50IGlzIG5vdCBjaGFuZ2luZy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbmV3RXh0ZW50XG4gKiBAZXhhbXBsZVxuICogdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG4gKi9cblBhaW50ZXIucHJvdG90eXBlLnNldEV4dGVudCA9IGZ1bmN0aW9uKG5ld0V4dGVudCkge1xuICAgIGlmICghbmV3RXh0ZW50IHx8IG5ld0V4dGVudCA9PT0gdGhpcy50aWxlRXh0ZW50KSByZXR1cm47XG5cbiAgICB0aGlzLnRpbGVFeHRlbnQgPSBuZXdFeHRlbnQ7XG5cbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgLy8gVGhlIHRpbGVFeHRlbnRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gYSBmdWxsICp0aWxlKlxuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlci5pdGVtU2l6ZSA9IDQ7XG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCA9IDQ7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudGlsZUV4dGVudEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShcbiAgICAgICAgZ2wuQVJSQVlfQlVGRkVSLFxuICAgICAgICBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICAvLyB0aWxlIGNvb3JkIHgsIHRpbGUgY29vcmQgeSwgdGV4dHVyZSBjb29yZCB4LCB0ZXh0dXJlIGNvb3JkIHlcbiAgICAgICAgICAgIDAsIDAsIDAsIDAsXG4gICAgICAgICAgICB0aGlzLnRpbGVFeHRlbnQsIDAsIDMyNzY3LCAwLFxuICAgICAgICAgICAgMCwgdGhpcy50aWxlRXh0ZW50LCAwLCAzMjc2NyxcbiAgICAgICAgICAgIHRoaXMudGlsZUV4dGVudCwgdGhpcy50aWxlRXh0ZW50LCAgMzI3NjcsIDMyNzY3XG4gICAgICAgIF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAvLyBUaGUgZGVidWdCdWZmZXIgaXMgdXNlZCB0byBkcmF3IHRpbGUgb3V0bGluZXMgZm9yIGRlYnVnZ2luZ1xuICAgIHRoaXMuZGVidWdCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1TaXplID0gMjtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1Db3VudCA9IDU7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuZGVidWdCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoXG4gICAgICAgIGdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgbmV3IEludDE2QXJyYXkoW1xuICAgICAgICAgICAgMCwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgMF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG59O1xuXG4vKlxuICogUmVzZXQgdGhlIGNvbG9yIGJ1ZmZlcnMgb2YgdGhlIGRyYXdpbmcgY2FudmFzLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5jbGVhckNvbG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5jbGVhckNvbG9yKDAsIDAsIDAsIDApO1xuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xufTtcblxuLypcbiAqIFJlc2V0IHRoZSBkcmF3aW5nIGNhbnZhcyBieSBjbGVhcmluZyB0aGUgc3RlbmNpbCBidWZmZXIgc28gdGhhdCB3ZSBjYW4gZHJhd1xuICogbmV3IHRpbGVzIGF0IHRoZSBzYW1lIGxvY2F0aW9uLCB3aGlsZSByZXRhaW5pbmcgcHJldmlvdXNseSBkcmF3biBwaXhlbHMuXG4gKi9cblBhaW50ZXIucHJvdG90eXBlLmNsZWFyU3RlbmNpbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhGRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdDbGlwcGluZ01hc2sgPSBmdW5jdGlvbih0aWxlKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5zd2l0Y2hTaGFkZXIodGhpcy5maWxsU2hhZGVyLCB0aWxlLnBvc01hdHJpeCk7XG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIENsZWFyIHRoZSBlbnRpcmUgc3RlbmNpbCBidWZmZXIsIGV4Y2VwdCBmb3IgdGhlIDd0aCBiaXQsIHdoaWNoIHN0b3Jlc1xuICAgIC8vIHRoZSBnbG9iYWwgY2xpcHBpbmcgbWFzayB0aGF0IGFsbG93cyB1cyB0byBhdm9pZCBkcmF3aW5nIGluIHJlZ2lvbnMgb2ZcbiAgICAvLyB0aWxlcyB3ZSd2ZSBhbHJlYWR5IHBhaW50ZWQgaW4uXG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhCRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIFRoZSBzdGVuY2lsIHRlc3Qgd2lsbCBmYWlsIGFsd2F5cywgbWVhbmluZyB3ZSBzZXQgYWxsIHBpeGVscyBjb3ZlcmVkXG4gICAgLy8gYnkgdGhpcyBnZW9tZXRyeSB0byAweDgwLiBXZSB1c2UgdGhlIGhpZ2hlc3QgYml0IDB4ODAgdG8gbWFyayB0aGUgcmVnaW9uc1xuICAgIC8vIHdlIHdhbnQgdG8gZHJhdyBpbi4gQWxsIHBpeGVscyB0aGF0IGhhdmUgdGhpcyBiaXQgKm5vdCogc2V0IHdpbGwgbmV2ZXIgYmVcbiAgICAvLyBkcmF3biBpbi5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHhDMCwgMHg0MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhDMCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLlJFUExBQ0UsIGdsLktFRVAsIGdsLktFRVApO1xuXG4gICAgLy8gRHJhdyB0aGUgY2xpcHBpbmcgbWFza1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgOCwgMCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLktFRVAsIGdsLktFRVAsIGdsLlJFUExBQ0UpO1xuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcbn07XG5cbi8vIE92ZXJyaWRkZW4gYnkgaGVhZGxlc3MgdGVzdHMuXG5QYWludGVyLnByb3RvdHlwZS5wcmVwYXJlQnVmZmVycyA9IGZ1bmN0aW9uKCkge307XG5QYWludGVyLnByb3RvdHlwZS5iaW5kRGVmYXVsdEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xufTtcblxudmFyIGRyYXcgPSB7XG4gICAgc3ltYm9sOiByZXF1aXJlKCcuL2RyYXdfc3ltYm9sJyksXG4gICAgbGluZTogcmVxdWlyZSgnLi9kcmF3X2xpbmUnKSxcbiAgICBmaWxsOiByZXF1aXJlKCcuL2RyYXdfZmlsbCcpLFxuICAgIHJhc3RlcjogcmVxdWlyZSgnLi9kcmF3X3Jhc3RlcicpLFxuICAgIGJhY2tncm91bmQ6IHJlcXVpcmUoJy4vZHJhd19iYWNrZ3JvdW5kJyksXG4gICAgZGVidWc6IHJlcXVpcmUoJy4vZHJhd19kZWJ1ZycpLFxuICAgIHZlcnRpY2VzOiByZXF1aXJlKCcuL2RyYXdfdmVydGljZXMnKVxufTtcblxuUGFpbnRlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24oc3R5bGUsIG9wdGlvbnMpIHtcbiAgICB0aGlzLnN0eWxlID0gc3R5bGU7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIHRoaXMubGluZUF0bGFzID0gc3R5bGUubGluZUF0bGFzO1xuXG4gICAgdGhpcy5zcHJpdGVBdGxhcyA9IHN0eWxlLnNwcml0ZUF0bGFzO1xuICAgIHRoaXMuc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHN0eWxlLnNwcml0ZSk7XG5cbiAgICB0aGlzLmdseXBoQXRsYXMgPSBzdHlsZS5nbHlwaEF0bGFzO1xuICAgIHRoaXMuZ2x5cGhBdGxhcy5iaW5kKHRoaXMuZ2wpO1xuXG4gICAgdGhpcy5mcmFtZUhpc3RvcnkucmVjb3JkKHRoaXMudHJhbnNmb3JtLnpvb20pO1xuXG4gICAgdGhpcy5wcmVwYXJlQnVmZmVycygpO1xuICAgIHRoaXMuY2xlYXJDb2xvcigpO1xuXG4gICAgZm9yICh2YXIgaSA9IHN0eWxlLl9ncm91cHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGdyb3VwID0gc3R5bGUuX2dyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHN0eWxlLnNvdXJjZXNbZ3JvdXAuc291cmNlXTtcblxuICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyU3RlbmNpbCgpO1xuICAgICAgICAgICAgc291cmNlLnJlbmRlcihncm91cCwgdGhpcyk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChncm91cC5zb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3TGF5ZXJzKGdyb3VwLCB0aGlzLmlkZW50aXR5TWF0cml4KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdUaWxlID0gZnVuY3Rpb24odGlsZSwgbGF5ZXJzKSB7XG4gICAgdGhpcy5zZXRFeHRlbnQodGlsZS50aWxlRXh0ZW50KTtcbiAgICB0aGlzLmRyYXdDbGlwcGluZ01hc2sodGlsZSk7XG4gICAgdGhpcy5kcmF3TGF5ZXJzKGxheWVycywgdGlsZS5wb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kZWJ1Zykge1xuICAgICAgICBkcmF3LmRlYnVnKHRoaXMsIHRpbGUpO1xuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdMYXllcnMgPSBmdW5jdGlvbihsYXllcnMsIG1hdHJpeCwgdGlsZSkge1xuICAgIGZvciAodmFyIGkgPSBsYXllcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5oaWRkZW4pXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBkcmF3W2xheWVyLnR5cGVdKHRoaXMsIGxheWVyLCBtYXRyaXgsIHRpbGUpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmVydGljZXMpIHtcbiAgICAgICAgICAgIGRyYXcudmVydGljZXModGhpcywgbGF5ZXIsIG1hdHJpeCwgdGlsZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBEcmF3cyBub24tb3BhcXVlIGFyZWFzLiBUaGlzIGlzIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG5QYWludGVyLnByb3RvdHlwZS5kcmF3U3RlbmNpbEJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHRoaXMuZmlsbFNoYWRlciwgdGhpcy5pZGVudGl0eU1hdHJpeCk7XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweDAwKTtcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG5cbiAgICAvLyBEcncgdGhlIGZpbGxpbmcgcXVhZCB3aGVyZSB0aGUgc3RlbmNpbCBidWZmZXIgaXNuJ3Qgc2V0LlxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wudW5pZm9ybTRmdih0aGlzLmZpbGxTaGFkZXIudV9jb2xvciwgWzAsIDAsIDAsIDAuNV0pO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59O1xuXG5QYWludGVyLnByb3RvdHlwZS50cmFuc2xhdGVNYXRyaXggPSBmdW5jdGlvbihtYXRyaXgsIHRpbGUsIHRyYW5zbGF0ZSwgYW5jaG9yKSB7XG4gICAgaWYgKCF0cmFuc2xhdGVbMF0gJiYgIXRyYW5zbGF0ZVsxXSkgcmV0dXJuIG1hdHJpeDtcblxuICAgIGlmIChhbmNob3IgPT09ICd2aWV3cG9ydCcpIHtcbiAgICAgICAgdmFyIHNpbkEgPSBNYXRoLnNpbigtdGhpcy50cmFuc2Zvcm0uYW5nbGUpO1xuICAgICAgICB2YXIgY29zQSA9IE1hdGguY29zKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHRyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVswXSAqIGNvc0EgLSB0cmFuc2xhdGVbMV0gKiBzaW5BLFxuICAgICAgICAgICAgdHJhbnNsYXRlWzBdICogc2luQSArIHRyYW5zbGF0ZVsxXSAqIGNvc0FcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICB2YXIgdGlsZVBpeGVsUmF0aW8gPSB0aGlzLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHRyYW5zbGF0aW9uID0gW1xuICAgICAgICB0cmFuc2xhdGVbMF0gLyB0aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdHJhbnNsYXRlWzFdIC8gdGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIDBcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBtYXQ0LnRyYW5zbGF0ZSh0cmFuc2xhdGVkTWF0cml4LCBtYXRyaXgsIHRyYW5zbGF0aW9uKTtcbiAgICByZXR1cm4gdHJhbnNsYXRlZE1hdHJpeDtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLnNhdmVUZXh0dXJlID0gZnVuY3Rpb24odGV4dHVyZSkge1xuICAgIHZhciB0ZXh0dXJlcyA9IHRoaXMucmV1c2FibGVUZXh0dXJlc1t0ZXh0dXJlLnNpemVdO1xuICAgIGlmICghdGV4dHVyZXMpIHtcbiAgICAgICAgdGhpcy5yZXVzYWJsZVRleHR1cmVzW3RleHR1cmUuc2l6ZV0gPSBbdGV4dHVyZV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHVyZXMucHVzaCh0ZXh0dXJlKTtcbiAgICB9XG59O1xuXG5cblBhaW50ZXIucHJvdG90eXBlLmdldFRleHR1cmUgPSBmdW5jdGlvbihzaXplKSB7XG4gICAgdmFyIHRleHR1cmVzID0gdGhpcy5yZXVzYWJsZVRleHR1cmVzW3NpemVdO1xuICAgIHJldHVybiB0ZXh0dXJlcyAmJiB0ZXh0dXJlcy5sZW5ndGggPiAwID8gdGV4dHVyZXMucG9wKCkgOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGdsaWZ5ID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBcImRlYnVnXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBmbG9hdCB1X3BvaW50c2l6ZTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcyxzdGVwKDMyNzY3LixhX3Bvcy54KSwxKTtnbF9Qb2ludFNpemU9dV9wb2ludHNpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZvaWQgbWFpbigpe2dsX0ZyYWdDb2xvcj11X2NvbG9yO31cIn0sXG4gICAgXCJkb3RcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBmbG9hdCB1X3NpemU7YXR0cmlidXRlIHZlYzIgYV9wb3M7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT11X3NpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3VuaWZvcm0gZmxvYXQgdV9ibHVyO3ZvaWQgbWFpbigpe2Zsb2F0IGEsYjthPWxlbmd0aChnbF9Qb2ludENvb3JkLS41KTtiPXNtb290aHN0ZXAoLjUsLjUtdV9ibHVyLGEpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmI7fVwifSxcbiAgICBcImZpbGxcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT0yLjt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXVfY29sb3I7fVwifSxcbiAgICBcImdhdXNzaWFuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X29mZnNldDt2YXJ5aW5nIHZlYzIgYVszXTt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dmVjMiBiPWdsX1Bvc2l0aW9uLnh5LzIuKy41O2FbMF09YjthWzFdPWIrdV9vZmZzZXQqMS4xODI0MjU1MjM4MDYzNTYzO2FbMl09Yi11X29mZnNldCoxLjE4MjQyNTUyMzgwNjM1NjM7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGFbM107dm9pZCBtYWluKCl7dmVjNCBiPXZlYzQoMCk7Yis9dGV4dHVyZTJEKHVfaW1hZ2UsYVswXSkqLjQwMjYxOTk0Njg5NDI0NzQ2O2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMV0pKi4yOTg2OTAwMjY1NTI4NzYzO2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMl0pKi4yOTg2OTAwMjY1NTI4NzYzO2dsX0ZyYWdDb2xvcj1iO31cIn0sXG4gICAgXCJsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW8sdV9leHRyYTt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGg7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBtYXQyIHVfYW50aWFsaWFzaW5nbWF0cml4O3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxlO2Q9YV9kYXRhLnh5O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTt2ZWM0IGY9dmVjNCh1X2xpbmV3aWR0aC5zKmQqLjAxNTg3MzAxNiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoZmxvb3IoYV9wb3MqLjUpK2YueHkvdV9yYXRpbywwLDEpO2Zsb2F0IGcsaCxpO2c9Z2xfUG9zaXRpb24ueS9nbF9Qb3NpdGlvbi53O2g9bGVuZ3RoKGQpL2xlbmd0aCh1X2FudGlhbGlhc2luZ21hdHJpeCpkKTtpPTEuLygxLi1nKnVfZXh0cmEpO2M9aSpoO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGgsdV9kYXNoYXJyYXk7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2JsdXI7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiLGM7dm9pZCBtYWluKCl7ZmxvYXQgZCxlLGY7ZD1sZW5ndGgoYSkqdV9saW5ld2lkdGgucztlPXVfYmx1cipjO2Y9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtZSksdV9saW5ld2lkdGgucy1kKS9lLDAuLDEuKTtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJsaW5lcGF0dGVyblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW87dW5pZm9ybSB2ZWMyIHVfbGluZXdpZHRoO3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZSxmLGc7Yz1hX2RhdGEueHk7ZmxvYXQgZD1hX2RhdGEueioxMjguK2FfZGF0YS53O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTtmPWMqLjAxNTg3MzAxNjtnPXVfbGluZXdpZHRoLnMqZjtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPWQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5fc2l6ZV9hLHVfcGF0dGVybl9zaXplX2IsdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBmbG9hdCB1X3BvaW50LHVfYmx1cix1X2ZhZGUsdV9vcGFjaXR5O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiO3ZvaWQgbWFpbigpe2Zsb2F0IGMsZCxlLGYsZyxoO2M9bGVuZ3RoKGEpKnVfbGluZXdpZHRoLnM7ZD1jbGFtcChtaW4oYy0odV9saW5ld2lkdGgudC11X2JsdXIpLHVfbGluZXdpZHRoLnMtYykvdV9ibHVyLDAuLDEuKTtlPW1vZChiL3VfcGF0dGVybl9zaXplX2EueCwxLik7Zj1tb2QoYi91X3BhdHRlcm5fc2l6ZV9iLngsMS4pO2c9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYS55O2g9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYi55O3ZlYzIgaSxqO2k9bWl4KHVfcGF0dGVybl90bF9hLHVfcGF0dGVybl9icl9hLHZlYzIoZSxnKSk7aj1taXgodV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2IsdmVjMihmLGgpKTt2ZWM0IGs9bWl4KHRleHR1cmUyRCh1X2ltYWdlLGkpLHRleHR1cmUyRCh1X2ltYWdlLGopLHVfZmFkZSk7ZCo9dV9vcGFjaXR5O2dsX0ZyYWdDb2xvcj1rKmQ7fVwifSxcbiAgICBcImxpbmVzZGZwYXR0ZXJuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5zY2FsZV9hLHVfcGF0dGVybnNjYWxlX2I7dW5pZm9ybSBmbG9hdCB1X3JhdGlvLHVfdGV4X3lfYSx1X3RleF95X2I7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxmO2Q9YV9kYXRhLnh5O2Zsb2F0IGU9YV9kYXRhLnoqMTI4LithX2RhdGEudztmPW1vZChhX3BvcywyLik7Zi55PXNpZ24oZi55LS41KTthPWY7dmVjNCBnPXZlYzQodV9saW5ld2lkdGgucypkKi4wMTU4NzMwMTYsMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPXZlYzIoZSp1X3BhdHRlcm5zY2FsZV9hLngsZi55KnVfcGF0dGVybnNjYWxlX2EueSt1X3RleF95X2EpO2M9dmVjMihlKnVfcGF0dGVybnNjYWxlX2IueCxmLnkqdV9wYXR0ZXJuc2NhbGVfYi55K3VfdGV4X3lfYik7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDt1bmlmb3JtIHZlYzQgdV9jb2xvcjt1bmlmb3JtIGZsb2F0IHVfYmx1cix1X3NkZmdhbW1hLHVfbWl4O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmLGcsaDtkPWxlbmd0aChhKSp1X2xpbmV3aWR0aC5zO2U9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtdV9ibHVyKSx1X2xpbmV3aWR0aC5zLWQpL3VfYmx1ciwwLiwxLik7Zj10ZXh0dXJlMkQodV9pbWFnZSxiKS5hO2c9dGV4dHVyZTJEKHVfaW1hZ2UsYykuYTtoPW1peChmLGcsdV9taXgpO2UqPXNtb290aHN0ZXAoLjUtdV9zZGZnYW1tYSwuNSt1X3NkZmdhbW1hLGgpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmU7fVwifSxcbiAgICBcIm91dGxpbmVcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfd29ybGQ7dmFyeWluZyB2ZWMyIGE7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4pLzIuKnVfd29ybGQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZvaWQgbWFpbigpe2Zsb2F0IGIsYztiPWxlbmd0aChhLWdsX0ZyYWdDb29yZC54eSk7Yz1zbW9vdGhzdGVwKDEuLDAuLGIpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmM7fVwifSxcbiAgICBcInBhdHRlcm5cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBtYXQzIHVfcGF0dGVybm1hdHJpeF9hLHVfcGF0dGVybm1hdHJpeF9iO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KHVfcGF0dGVybm1hdHJpeF9hKnZlYzMoYV9wb3MsMSkpLnh5O2I9KHVfcGF0dGVybm1hdHJpeF9iKnZlYzMoYV9wb3MsMSkpLnh5O31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIGZsb2F0IHVfb3BhY2l0eSx1X21peDt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgYSxiO3ZvaWQgbWFpbigpe3ZlYzIgYyxkLGYsZztjPW1vZChhLDEuKTtkPW1peCh1X3BhdHRlcm5fdGxfYSx1X3BhdHRlcm5fYnJfYSxjKTt2ZWM0IGUsaDtlPXRleHR1cmUyRCh1X2ltYWdlLGQpO2Y9bW9kKGIsMS4pO2c9bWl4KHVfcGF0dGVybl90bF9iLHVfcGF0dGVybl9icl9iLGYpO2g9dGV4dHVyZTJEKHVfaW1hZ2UsZyk7Z2xfRnJhZ0NvbG9yPW1peChlLGgsdV9taXgpKnVfb3BhY2l0eTt9XCJ9LFxuICAgIFwicmFzdGVyXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3RsX3BhcmVudDt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfcGFyZW50LHVfYnVmZmVyX3NjYWxlO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfdGV4dHVyZV9wb3M7dmFyeWluZyB2ZWMyIGEsYjt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7YT0oYV90ZXh0dXJlX3Bvcy8zMjc2Ny4tLjUpL3VfYnVmZmVyX3NjYWxlKy41O2I9YSp1X3NjYWxlX3BhcmVudCt1X3RsX3BhcmVudDt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X29wYWNpdHkwLHVfb3BhY2l0eTEsdV9icmlnaHRuZXNzX2xvdyx1X2JyaWdodG5lc3NfaGlnaCx1X3NhdHVyYXRpb25fZmFjdG9yLHVfY29udHJhc3RfZmFjdG9yO3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2UwLHVfaW1hZ2UxO3ZhcnlpbmcgdmVjMiBhLGI7dW5pZm9ybSB2ZWMzIHVfc3Bpbl93ZWlnaHRzO3ZvaWQgbWFpbigpe3ZlYzQgYyxkLGU7Yz10ZXh0dXJlMkQodV9pbWFnZTAsYSk7ZD10ZXh0dXJlMkQodV9pbWFnZTEsYik7ZT1jKnVfb3BhY2l0eTArZCp1X29wYWNpdHkxO3ZlYzMgZixoLGk7Zj1lLnJnYjtmPXZlYzMoZG90KGYsdV9zcGluX3dlaWdodHMueHl6KSxkb3QoZix1X3NwaW5fd2VpZ2h0cy56eHkpLGRvdChmLHVfc3Bpbl93ZWlnaHRzLnl6eCkpO2Zsb2F0IGc9KGUucitlLmcrZS5iKS8zLjtmKz0oZy1mKSp1X3NhdHVyYXRpb25fZmFjdG9yO2Y9KGYtLjUpKnVfY29udHJhc3RfZmFjdG9yKy41O2g9dmVjMyh1X2JyaWdodG5lc3NfbG93KTtpPXZlYzModV9icmlnaHRuZXNzX2hpZ2gpO2dsX0ZyYWdDb2xvcj12ZWM0KG1peChoLGksZiksZS5hKTt9XCJ9LFxuICAgIFwiaWNvblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfb2Zmc2V0O2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTEsYV9kYXRhMjt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfem9vbSx1X2ZhZGVkaXN0LHVfbWluZmFkZXpvb20sdV9tYXhmYWRlem9vbSx1X2ZhZGV6b29tLHVfb3BhY2l0eSx1X2V4dHJhO3VuaWZvcm0gYm9vbCB1X3NrZXdlZDt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZTtjPWFfZGF0YTEueHk7ZmxvYXQgZCxmLGcsaCxpLGo7ZD1hX2RhdGExWzJdO2U9YV9kYXRhMi5zdDtmPWVbMF07Zz1lWzFdO2g9MTAuO2k9Mi4tc3RlcChmLHVfem9vbSktKDEuLXN0ZXAoZyx1X3pvb20pKTtqPWNsYW1wKCh1X2ZhZGV6b29tLWQpL3VfZmFkZWRpc3QsMC4sMS4pO2lmKHVfZmFkZWRpc3Q+PTAuKWI9ajtlbHNlIGI9MS4tajtpZih1X21heGZhZGV6b29tPGQpYj0wLjtpZih1X21pbmZhZGV6b29tPj1kKWI9MS47aSs9c3RlcChiLDAuKTtpZih1X3NrZXdlZCl7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4sMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zK2sueHksMCwxKTtnbF9Qb3NpdGlvbi56Kz1pKmdsX1Bvc2l0aW9uLnc7fWVsc2V7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4saSwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSkrazt9YT1jL3VfdGV4c2l6ZTtiKj11X29wYWNpdHk7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGI7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXRleHR1cmUyRCh1X3RleHR1cmUsYSkqYjt9XCJ9LFxuICAgIFwic2RmXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3MsYV9vZmZzZXQ7YXR0cmlidXRlIHZlYzQgYV9kYXRhMSxhX2RhdGEyO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gZmxvYXQgdV96b29tLHVfZmFkZWRpc3QsdV9taW5mYWRlem9vbSx1X21heGZhZGV6b29tLHVfZmFkZXpvb20sdV9leHRyYTt1bmlmb3JtIGJvb2wgdV9za2V3ZWQ7dW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGIsYzt2b2lkIG1haW4oKXt2ZWMyIGQsZjtkPWFfZGF0YTEueHk7ZmxvYXQgZSxnLGgsaSxqLGssbDtlPWFfZGF0YTFbMl07Zj1hX2RhdGEyLnN0O2c9ZlswXTtoPWZbMV07aT0yLi1zdGVwKGcsdV96b29tKS0oMS4tc3RlcChoLHVfem9vbSkpO2o9Y2xhbXAoKHVfZmFkZXpvb20tZSkvdV9mYWRlZGlzdCwwLiwxLik7aWYodV9mYWRlZGlzdD49MC4pYj1qO2Vsc2UgYj0xLi1qO2lmKHVfbWF4ZmFkZXpvb208ZSliPTAuO2lmKHVfbWluZmFkZXpvb20+PWUpYj0xLjtpKz1zdGVwKGIsMC4pO2lmKHVfc2tld2VkKXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3Mray54eSwwLDEpO2dsX1Bvc2l0aW9uLnorPWkqZ2xfUG9zaXRpb24udzt9ZWxzZXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LixpLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKStrO31rPWdsX1Bvc2l0aW9uLnkvZ2xfUG9zaXRpb24udztsPTEuLygxLi1rKnVfZXh0cmEpO2M9bDthPWQvdV90ZXhzaXplO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHNhbXBsZXIyRCB1X3RleHR1cmU7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2J1ZmZlcix1X2dhbW1hO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmO2Q9dV9nYW1tYSpjO2U9dGV4dHVyZTJEKHVfdGV4dHVyZSxhKS5hO2Y9c21vb3Roc3RlcCh1X2J1ZmZlci1kLHVfYnVmZmVyK2QsZSkqYjtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJjb2xsaXNpb25ib3hcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3BvcyxhX2V4dHJ1ZGUsYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfc2NhbGU7dmFyeWluZyBmbG9hdCBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcythX2V4dHJ1ZGUvdV9zY2FsZSwwLDEpO2E9YV9kYXRhLng7Yj1hX2RhdGEueTt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X3pvb20sdV9tYXh6b29tO3ZhcnlpbmcgZmxvYXQgYSxiO3ZvaWQgbWFpbigpe2Zsb2F0IGM9LjU7Z2xfRnJhZ0NvbG9yPXZlYzQoMCwxLDAsMSkqYztpZihiPnVfem9vbSlnbF9GcmFnQ29sb3I9dmVjNCgxLDAsMCwxKSpjO2lmKHVfem9vbT49YSlnbF9GcmFnQ29sb3I9dmVjNCgwLDAsMCwxKSpjKi4yNTtpZihiPj11X21heHpvb20pZ2xfRnJhZ0NvbG9yPXZlYzQoMCwwLDEsMSkqYyouMjt9XCJ9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQnKTtcbnZhciBUaWxlUHlyYW1pZCA9IHJlcXVpcmUoJy4vdGlsZV9weXJhbWlkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcbnZhciB1cmxSZXNvbHZlID0gcmVxdWlyZSgncmVzb2x2ZS11cmwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHZW9KU09OU291cmNlO1xuXG4vKipcbiAqIENyZWF0ZSBhIEdlb0pTT04gZGF0YSBzb3VyY2UgaW5zdGFuY2UgZ2l2ZW4gYW4gb3B0aW9ucyBvYmplY3RcbiAqIEBjbGFzcyBHZW9KU09OU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IG9wdGlvbnMuZGF0YSBBIEdlb0pTT04gZGF0YSBvYmplY3Qgb3IgVVJMIHRvIGl0LiBUaGUgbGF0dGVyIGlzIHByZWZlcmFibGUgaW4gY2FzZSBvZiBsYXJnZSBHZW9KU09OIGZpbGVzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heHpvb209MTRdIE1heGltdW0gem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgYXQuXG4gKiBAZXhhbXBsZVxuICogdmFyIHNvdXJjZU9iaiA9IG5ldyBtYXBib3hnbC5HZW9KU09OU291cmNlKHtcbiAqICAgIGRhdGE6IHtcbiAqICAgICAgICBcInR5cGVcIjogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICogICAgICAgIFwiZmVhdHVyZXNcIjogW3tcbiAqICAgICAgICAgICAgXCJ0eXBlXCI6IFwiRmVhdHVyZVwiLFxuICogICAgICAgICAgICBcImdlb21ldHJ5XCI6IHtcbiAqICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIlBvaW50XCIsXG4gKiAgICAgICAgICAgICAgICBcImNvb3JkaW5hdGVzXCI6IFtcbiAqICAgICAgICAgICAgICAgICAgICAtNzYuNTMwNjMyOTcyNzE3MjksXG4gKiAgICAgICAgICAgICAgICAgICAgMzkuMTgxNzQwNzc5OTQxMDhcbiAqICAgICAgICAgICAgICAgIF1cbiAqICAgICAgICAgICAgfVxuICogICAgICAgIH1dXG4gKiAgICB9XG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBHZW9KU09OU291cmNlKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIHRoaXMuX2RhdGEgPSBvcHRpb25zLmRhdGE7XG5cbiAgICBpZiAob3B0aW9ucy5tYXh6b29tICE9PSB1bmRlZmluZWQpIHRoaXMubWF4em9vbSA9IG9wdGlvbnMubWF4em9vbTtcblxuICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICB0aWxlU2l6ZTogNTEyLFxuICAgICAgICBtaW56b29tOiB0aGlzLm1pbnpvb20sXG4gICAgICAgIG1heHpvb206IHRoaXMubWF4em9vbSxcbiAgICAgICAgY2FjaGVTaXplOiAyMCxcbiAgICAgICAgbG9hZDogdGhpcy5fbG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICB1bmxvYWQ6IHRoaXMuX3VubG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWRkOiB0aGlzLl9hZGRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpXG4gICAgfSk7XG59XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEV2ZW50ZWQsIC8qKiBAbGVuZHMgR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUgKi97XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAxNCxcbiAgICBfZGlydHk6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgc291cmNlIGdlb2pzb24gZGF0YSBhbmQgcmVyZW5kZXIgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGRhdGEgQSBHZW9KU09OIGRhdGEgb2JqZWN0IG9yIFVSTCB0byBpdC4gVGhlIGxhdHRlciBpcyBwcmVmZXJhYmxlIGluIGNhc2Ugb2YgbGFyZ2UgR2VvSlNPTiBmaWxlcy5cbiAgICAgKiBAcmV0dXJucyB7R2VvSlNPTlNvdXJjZX0gdGhpc1xuICAgICAqL1xuICAgIHNldERhdGE6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScpO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcClcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHRoaXMubWFwLnRyYW5zZm9ybSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkZWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX2RpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEYXRhKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVuZGVyOiBTb3VyY2UuX3JlbmRlclRpbGVzLFxuICAgIGZlYXR1cmVzQXQ6IFNvdXJjZS5fdmVjdG9yRmVhdHVyZXNBdCxcblxuICAgIF91cGRhdGVEYXRhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkYXRhID0gdXJsUmVzb2x2ZSh3aW5kb3cubG9jYXRpb24uaHJlZiwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdwYXJzZSBnZW9qc29uJywge1xuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHRpbGVTaXplOiA1MTIsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb21cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyKSB7XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcblxuICAgICAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuXG4gICAgX2xvYWRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUuY29vcmQueiA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHRpbGUuY29vcmQueiAtIHRoaXMubWF4em9vbSkgOiAxO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgdWlkOiB0aWxlLnVpZCxcbiAgICAgICAgICAgIGNvb3JkOiB0aWxlLmNvb3JkLFxuICAgICAgICAgICAgem9vbTogdGlsZS5jb29yZC56LFxuICAgICAgICAgICAgbWF4Wm9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgdGlsZVNpemU6IDUxMixcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5pZCxcbiAgICAgICAgICAgIG92ZXJzY2FsaW5nOiBvdmVyc2NhbGluZyxcbiAgICAgICAgICAgIGFuZ2xlOiB0aGlzLm1hcC50cmFuc2Zvcm0uYW5nbGUsXG4gICAgICAgICAgICBwaXRjaDogdGhpcy5tYXAudHJhbnNmb3JtLnBpdGNoLFxuICAgICAgICAgICAgY29sbGlzaW9uRGVidWc6IHRoaXMubWFwLmNvbGxpc2lvbkRlYnVnXG4gICAgICAgIH07XG5cbiAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIGdlb2pzb24gdGlsZScsIHBhcmFtcywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG5cbiAgICAgICAgICAgIHRpbGUudW5sb2FkVmVjdG9yRGF0YSh0aGlzLm1hcC5wYWludGVyKTtcblxuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGlsZS5sb2FkVmVjdG9yRGF0YShkYXRhKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5sb2FkJywge3RpbGU6IHRpbGV9KTtcblxuICAgICAgICB9LmJpbmQodGhpcyksIHRoaXMud29ya2VySUQpO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCd2ZWN0b3ItdGlsZScpLlZlY3RvclRpbGVGZWF0dXJlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlb0pTT05XcmFwcGVyO1xuXG4vLyBjb25mb3JtIHRvIHZlY3RvcnRpbGUgYXBpXG5mdW5jdGlvbiBHZW9KU09OV3JhcHBlcihmZWF0dXJlcykge1xuICAgIHRoaXMuZmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICB0aGlzLmxlbmd0aCA9IGZlYXR1cmVzLmxlbmd0aDtcbn1cblxuR2VvSlNPTldyYXBwZXIucHJvdG90eXBlLmZlYXR1cmUgPSBmdW5jdGlvbihpKSB7XG4gICAgcmV0dXJuIG5ldyBGZWF0dXJlV3JhcHBlcih0aGlzLmZlYXR1cmVzW2ldKTtcbn07XG5cbmZ1bmN0aW9uIEZlYXR1cmVXcmFwcGVyKGZlYXR1cmUpIHtcbiAgICB0aGlzLnR5cGUgPSBmZWF0dXJlLnR5cGU7XG4gICAgdGhpcy5yYXdHZW9tZXRyeSA9IGZlYXR1cmUudHlwZSA9PT0gMSA/IFtmZWF0dXJlLmdlb21ldHJ5XSA6IGZlYXR1cmUuZ2VvbWV0cnk7XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gZmVhdHVyZS50YWdzO1xuICAgIHRoaXMuZXh0ZW50ID0gNDA5Njtcbn1cblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByaW5ncyA9IHRoaXMucmF3R2VvbWV0cnk7XG4gICAgdGhpcy5nZW9tZXRyeSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmluZyA9IHJpbmdzW2ldLFxuICAgICAgICAgICAgbmV3UmluZyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG5ld1JpbmcucHVzaChuZXcgUG9pbnQocmluZ1tqXVswXSwgcmluZ1tqXVsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2VvbWV0cnkucHVzaChuZXdSaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnk7XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5nZW9tZXRyeSkgdGhpcy5sb2FkR2VvbWV0cnkoKTtcblxuICAgIHZhciByaW5ncyA9IHRoaXMuZ2VvbWV0cnksXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjb29yZCA9IHJpbmdbal07XG5cbiAgICAgICAgICAgIHgxID0gTWF0aC5taW4oeDEsIGNvb3JkLngpO1xuICAgICAgICAgICAgeDIgPSBNYXRoLm1heCh4MiwgY29vcmQueCk7XG4gICAgICAgICAgICB5MSA9IE1hdGgubWluKHkxLCBjb29yZC55KTtcbiAgICAgICAgICAgIHkyID0gTWF0aC5tYXgoeTIsIGNvb3JkLnkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4MSwgeTEsIHgyLCB5Ml07XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUudG9HZW9KU09OID0gVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlJyk7XG52YXIgbm9ybWFsaXplVVJMID0gcmVxdWlyZSgnLi4vdXRpbC9tYXBib3gnKS5ub3JtYWxpemVUaWxlVVJMO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhc3RlclRpbGVTb3VyY2U7XG5cbmZ1bmN0aW9uIFJhc3RlclRpbGVTb3VyY2Uob3B0aW9ucykge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHV0aWwucGljayhvcHRpb25zLCBbJ3VybCcsICd0aWxlU2l6ZSddKSk7XG5cbiAgICBTb3VyY2UuX2xvYWRUaWxlSlNPTi5jYWxsKHRoaXMsIG9wdGlvbnMpO1xufVxuXG5SYXN0ZXJUaWxlU291cmNlLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChFdmVudGVkLCB7XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAyMixcbiAgICB0aWxlU2l6ZTogNTEyLFxuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB9LFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3B5cmFtaWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX3B5cmFtaWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5cmFtaWQudXBkYXRlKHRoaXMudXNlZCwgdHJhbnNmb3JtLCB0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcblxuICAgIF9sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBhamF4LmdldEltYWdlKG5vcm1hbGl6ZVVSTCh0aWxlLmNvb3JkLnVybCh0aGlzLnRpbGVzKSwgdGhpcy51cmwpLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGdsID0gdGhpcy5tYXAucGFpbnRlci5nbDtcbiAgICAgICAgICAgIHRpbGUudGV4dHVyZSA9IHRoaXMubWFwLnBhaW50ZXIuZ2V0VGV4dHVyZShpbWcud2lkdGgpO1xuICAgICAgICAgICAgaWYgKHRpbGUudGV4dHVyZSkge1xuICAgICAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRpbGUudGV4dHVyZSk7XG4gICAgICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCAwLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aWxlLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSX01JUE1BUF9ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGltZyk7XG4gICAgICAgICAgICAgICAgdGlsZS50ZXh0dXJlLnNpemUgPSBpbWcud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnbC5nZW5lcmF0ZU1pcG1hcChnbC5URVhUVVJFXzJEKTtcblxuICAgICAgICAgICAgdGlsZS50aW1lQWRkZWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHRoaXMubWFwLmFuaW1hdGlvbkxvb3Auc2V0KHRoaXMuc3R5bGUucmFzdGVyRmFkZUR1cmF0aW9uKTtcblxuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGlsZS5sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUubG9hZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9hYm9ydFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS5hYm9ydGVkID0gdHJ1ZTtcbiAgICB9LFxuXG4gICAgX2FkZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmFkZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmVUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5yZW1vdmUnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfdW5sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBpZiAodGlsZS50ZXh0dXJlKSB0aGlzLm1hcC5wYWludGVyLnNhdmVUZXh0dXJlKHRpbGUudGV4dHVyZSk7XG4gICAgfSxcblxuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFRpbGVQeXJhbWlkID0gcmVxdWlyZSgnLi90aWxlX3B5cmFtaWQnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBub3JtYWxpemVVUkwgPSByZXF1aXJlKCcuLi91dGlsL21hcGJveCcpLm5vcm1hbGl6ZVNvdXJjZVVSTDtcblxuZXhwb3J0cy5fbG9hZFRpbGVKU09OID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciBsb2FkZWQgPSBmdW5jdGlvbihlcnIsIHRpbGVKU09OKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKHRpbGVKU09OLFxuICAgICAgICAgICAgWyd0aWxlcycsICdtaW56b29tJywgJ21heHpvb20nLCAnYXR0cmlidXRpb24nXSkpO1xuXG4gICAgICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICAgICAgdGlsZVNpemU6IHRoaXMudGlsZVNpemUsXG4gICAgICAgICAgICBjYWNoZVNpemU6IDIwLFxuICAgICAgICAgICAgbWluem9vbTogdGhpcy5taW56b29tLFxuICAgICAgICAgICAgbWF4em9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgcmVwYXJzZU92ZXJzY2FsZWQ6IHRoaXMucmVwYXJzZU92ZXJzY2FsZWQsXG4gICAgICAgICAgICBsb2FkOiB0aGlzLl9sb2FkVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgdW5sb2FkOiB0aGlzLl91bmxvYWRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgICAgICBhZGQ6IHRoaXMuX2FkZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcmVkb1BsYWNlbWVudDogdGhpcy5fcmVkb1RpbGVQbGFjZW1lbnQgPyB0aGlzLl9yZWRvVGlsZVBsYWNlbWVudC5iaW5kKHRoaXMpIDogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmlyZSgnbG9hZCcpO1xuICAgIH0uYmluZCh0aGlzKTtcblxuICAgIGlmIChvcHRpb25zLnVybCkge1xuICAgICAgICBhamF4LmdldEpTT04obm9ybWFsaXplVVJMKG9wdGlvbnMudXJsKSwgbG9hZGVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBicm93c2VyLmZyYW1lKGxvYWRlZC5iaW5kKHRoaXMsIG51bGwsIG9wdGlvbnMpKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl9yZW5kZXJUaWxlcyA9IGZ1bmN0aW9uKGxheWVycywgcGFpbnRlcikge1xuICAgIGlmICghdGhpcy5fcHlyYW1pZClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQucmVuZGVyZWRJRHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3B5cmFtaWQuZ2V0VGlsZShpZHNbaV0pLFxuICAgICAgICAgICAgLy8gY29vcmQgaXMgZGlmZmVyZW50IHRoYW4gdGlsZS5jb29yZCBmb3Igd3JhcHBlZCB0aWxlcyBzaW5jZSB0aGUgYWN0dWFsXG4gICAgICAgICAgICAvLyB0aWxlIG9iamVjdCBpcyBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlIHZpc2libGUgY29waWVzIG9mIHRoYXQgdGlsZS5cbiAgICAgICAgICAgIGNvb3JkID0gVGlsZUNvb3JkLmZyb21JRChpZHNbaV0pLFxuICAgICAgICAgICAgeiA9IGNvb3JkLnosXG4gICAgICAgICAgICB4ID0gY29vcmQueCxcbiAgICAgICAgICAgIHkgPSBjb29yZC55LFxuICAgICAgICAgICAgdyA9IGNvb3JkLnc7XG5cbiAgICAgICAgLy8gaWYgeiA+IG1heHpvb20gdGhlbiB0aGUgdGlsZSBpcyBhY3R1YWxseSBhIG92ZXJzY2FsZWQgbWF4em9vbSB0aWxlLFxuICAgICAgICAvLyBzbyBjYWxjdWxhdGUgdGhlIG1hdHJpeCB0aGUgbWF4em9vbSB0aWxlIHdvdWxkIHVzZS5cbiAgICAgICAgeiA9IE1hdGgubWluKHosIHRoaXMubWF4em9vbSk7XG5cbiAgICAgICAgeCArPSB3ICogKDEgPDwgeik7XG4gICAgICAgIHRpbGUuY2FsY3VsYXRlTWF0cmljZXMoeiwgeCwgeSwgcGFpbnRlci50cmFuc2Zvcm0sIHBhaW50ZXIpO1xuXG4gICAgICAgIHBhaW50ZXIuZHJhd1RpbGUodGlsZSwgbGF5ZXJzKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl92ZWN0b3JGZWF0dXJlc0F0ID0gZnVuY3Rpb24oY29vcmQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuX3B5cmFtaWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBbXSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gdGhpcy5fcHlyYW1pZC50aWxlQXQoY29vcmQpO1xuICAgIGlmICghcmVzdWx0KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuXG4gICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3F1ZXJ5IGZlYXR1cmVzJywge1xuICAgICAgICB1aWQ6IHJlc3VsdC50aWxlLnVpZCxcbiAgICAgICAgeDogcmVzdWx0LngsXG4gICAgICAgIHk6IHJlc3VsdC55LFxuICAgICAgICBzY2FsZTogcmVzdWx0LnNjYWxlLFxuICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfSwgY2FsbGJhY2ssIHJlc3VsdC50aWxlLndvcmtlcklEKTtcbn07XG5cbi8qXG4gKiBDcmVhdGUgYSB0aWxlZCBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50eXBlIEVpdGhlciBgcmFzdGVyYCBvciBgdmVjdG9yYC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCBBIHRpbGUgc291cmNlIFVSTC4gVGhpcyBzaG91bGQgZWl0aGVyIGJlIGBtYXBib3g6Ly97bWFwaWR9YCBvciBhIGZ1bGwgYGh0dHBbc11gIHVybCB0aGF0IHBvaW50cyB0byBhIFRpbGVKU09OIGVuZHBvaW50LlxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy50aWxlcyBBbiBhcnJheSBvZiB0aWxlIHNvdXJjZXMuIElmIGB1cmxgIGlzIG5vdCBzcGVjaWZpZWQsIGB0aWxlc2AgY2FuIGJlIHVzZWQgaW5zdGVhZCB0byBzcGVjaWZ5IHRpbGUgc291cmNlcywgYXMgaW4gdGhlIFRpbGVKU09OIHNwZWMuIE90aGVyIFRpbGVKU09OIGtleXMgc3VjaCBhcyBgbWluem9vbWAgYW5kIGBtYXh6b29tYCBjYW4gYmUgc3BlY2lmaWVkIGluIGEgc291cmNlIG9iamVjdCBpZiBgdGlsZXNgIGlzIHVzZWQuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5pZCBBbiBvcHRpb25hbCBgaWRgIHRvIGFzc2lnbiB0byB0aGUgc291cmNlXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGlsZVNpemU9NTEyXSBPcHRpb25hbCB0aWxlIHNpemUgKHdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzLCBhc3N1bWluZyB0aWxlcyBhcmUgc3F1YXJlKS4gVGhpcyBvcHRpb24gaXMgb25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBzb3VyY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5jYWNoZVNpemUgT3B0aW9uYWwgbWF4IG51bWJlciBvZiB0aWxlcyB0byBjYWNoZSBhdCBhbnkgZ2l2ZW4gdGltZVxuICogQGV4YW1wbGVcbiAqIHZhciBzb3VyY2VPYmogPSBuZXcgbWFwYm94Z2wuU291cmNlLmNyZWF0ZSh7XG4gKiAgICB0eXBlOiAndmVjdG9yJyxcbiAqICAgIHVybDogJ21hcGJveDovL21hcGJveC5tYXBib3gtc3RyZWV0cy12NSdcbiAqIH0pO1xuICogbWFwLmFkZFNvdXJjZSgnc29tZSBpZCcsIHNvdXJjZU9iaik7IC8vIGFkZFxuICogbWFwLnJlbW92ZVNvdXJjZSgnc29tZSBpZCcpOyAgLy8gcmVtb3ZlXG4gKi9cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24oc291cmNlKSB7XG4gICAgLy8gVGhpcyBpcyBub3QgYXQgZmlsZSBzY29wZSBpbiBvcmRlciB0byBhdm9pZCBhIGNpcmN1bGFyIHJlcXVpcmUuXG4gICAgdmFyIHNvdXJjZXMgPSB7XG4gICAgICAgIHZlY3RvcjogcmVxdWlyZSgnLi92ZWN0b3JfdGlsZV9zb3VyY2UnKSxcbiAgICAgICAgcmFzdGVyOiByZXF1aXJlKCcuL3Jhc3Rlcl90aWxlX3NvdXJjZScpLFxuICAgICAgICBnZW9qc29uOiByZXF1aXJlKCcuL2dlb2pzb25fc291cmNlJyksXG4gICAgICAgIHZpZGVvOiByZXF1aXJlKCcuL3ZpZGVvX3NvdXJjZScpXG4gICAgfTtcblxuICAgIGZvciAodmFyIHR5cGUgaW4gc291cmNlcykge1xuICAgICAgICBpZiAoc291cmNlIGluc3RhbmNlb2Ygc291cmNlc1t0eXBlXSkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgc291cmNlc1tzb3VyY2UudHlwZV0oc291cmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpO1xudmFyIG1hdDIgPSBnbG1hdHJpeC5tYXQyO1xudmFyIG1hdDQgPSBnbG1hdHJpeC5tYXQ0O1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXJTZXQgPSByZXF1aXJlKCcuLi9kYXRhL2J1ZmZlci9idWZmZXJfc2V0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZTtcblxuLyoqXG4gKiBBIHRpbGUgb2JqZWN0IGlzIHRoZSBjb21iaW5hdGlvbiBvZiBhIENvb3JkaW5hdGUsIHdoaWNoIGRlZmluZXNcbiAqIGl0cyBwbGFjZSwgYXMgd2VsbCBhcyBhIHVuaXF1ZSBJRCBhbmQgZGF0YSB0cmFja2luZyBmb3IgaXRzIGNvbnRlbnRcbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZVxuICovXG5mdW5jdGlvbiBUaWxlKGNvb3JkLCBzaXplKSB7XG4gICAgdGhpcy5jb29yZCA9IGNvb3JkO1xuICAgIHRoaXMudWlkID0gdXRpbC51bmlxdWVJZCgpO1xuICAgIHRoaXMubG9hZGVkID0gZmFsc2U7XG4gICAgdGhpcy51c2VzID0gMDtcbiAgICB0aGlzLnRpbGVTaXplID0gc2l6ZTtcbn1cblxuVGlsZS5wcm90b3R5cGUgPSB7XG4gICAgLy8gdG9kbyB1bmhhcmRjb2RlXG4gICAgdGlsZUV4dGVudDogNDA5NixcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgaW50ZXJuYWwgcG9zTWF0cml4IHRoYXQgdGhpcyB0aWxlIHVzZXMgdG8gZGlzcGxheVxuICAgICAqIGl0c2VsZiBpbiBhIG1hcCwgZ2l2ZW4gYSBjb29yZGluYXRlIGFzICh6LCB4LCB5KSBhbmQgYSB0cmFuc2Zvcm1cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gelxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICovXG4gICAgY2FsY3VsYXRlTWF0cmljZXM6IGZ1bmN0aW9uKHosIHgsIHksIHRyYW5zZm9ybSkge1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgbW9kZWwtdmlldyBtYXRyaXggdGhhdCBjb252ZXJ0cyBmcm9tIHRoZSB0aWxlIGNvb3JkaW5hdGVzXG4gICAgICAgIC8vIHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAgICAgICAgdmFyIHRpbGVTY2FsZSA9IE1hdGgucG93KDIsIHopO1xuICAgICAgICB2YXIgc2NhbGUgPSB0cmFuc2Zvcm0ud29ybGRTaXplIC8gdGlsZVNjYWxlO1xuXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZVxuICAgICAgICB0aGlzLnNjYWxlID0gc2NhbGU7XG5cbiAgICAgICAgLy8gVGhlIHBvc2l0aW9uIG1hdHJpeFxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDY0QXJyYXkoMTYpO1xuICAgICAgICBtYXQ0LmlkZW50aXR5KHRoaXMucG9zTWF0cml4KTtcbiAgICAgICAgbWF0NC50cmFuc2xhdGUodGhpcy5wb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4LCBbeCAqIHNjYWxlLCB5ICogc2NhbGUsIDBdKTtcblxuICAgICAgICBtYXQ0LnNjYWxlKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgWyBzY2FsZSAvIHRoaXMudGlsZUV4dGVudCwgc2NhbGUgLyB0aGlzLnRpbGVFeHRlbnQsIDEgXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkodGhpcy5wb3NNYXRyaXgsIHRyYW5zZm9ybS5nZXRQcm9qTWF0cml4KCksIHRoaXMucG9zTWF0cml4KTtcblxuICAgICAgICAvLyBUaGUgZXh0cnVzaW9uIG1hdHJpeC5cbiAgICAgICAgdGhpcy5leE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIG1hdDQub3J0aG8odGhpcy5leE1hdHJpeCwgMCwgdHJhbnNmb3JtLndpZHRoLCB0cmFuc2Zvcm0uaGVpZ2h0LCAwLCAwLCAtMSk7XG4gICAgICAgIC8vbWF0NC5yb3RhdGVaKHRoaXMuZXhNYXRyaXgsIHRoaXMuZXhNYXRyaXgsIC10cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgICAgIC8vIDJ4MiBtYXRyaXggZm9yIHJvdGF0aW5nIHBvaW50c1xuICAgICAgICB0aGlzLnJvdGF0aW9uTWF0cml4ID0gbWF0Mi5jcmVhdGUoKTtcbiAgICAgICAgbWF0Mi5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCwgdGhpcy5yb3RhdGlvbk1hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcblxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5wb3NNYXRyaXgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGNvb3JkaW5hdGUgcG9zaXRpb24sIHpvb20gdGhhdCBjb29yZGluYXRlIHRvIG15IHpvb20gYW5kXG4gICAgICogc2NhbGUgYW5kIHJldHVybiBhIHBvc2l0aW9uIGluIHgsIHksIHNjYWxlXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHBvc2l0aW9uXG4gICAgICovXG4gICAgcG9zaXRpb25BdDogZnVuY3Rpb24oY29vcmQsIHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgY29vcmQgPSBjb29yZC56b29tVG8oTWF0aC5taW4odGhpcy5jb29yZC56LCBzb3VyY2VNYXhab29tKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiAoY29vcmQuY29sdW1uIC0gdGhpcy5jb29yZC54KSAqIDQwOTYsXG4gICAgICAgICAgICB5OiAoY29vcmQucm93IC0gdGhpcy5jb29yZC55KSAqIDQwOTYsXG4gICAgICAgICAgICBzY2FsZTogdGhpcy5zY2FsZVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGRhdGEgb2JqZWN0IHdpdGggYSAnYnVmZmVycycgcHJvcGVydHksIGxvYWQgaXQgaW50b1xuICAgICAqIHRoaXMgdGlsZSdzIGVsZW1lbnRHcm91cHMgYW5kIGJ1ZmZlcnMgcHJvcGVydGllcyBhbmQgc2V0IGxvYWRlZFxuICAgICAqIHRvIHRydWUuIElmIHRoZSBkYXRhIGlzIG51bGwsIGxpa2UgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHlcbiAgICAgKiBHZW9KU09OIHRpbGUsIG5vLW9wIGJ1dCBzdGlsbCBzZXQgbG9hZGVkIHRvIHRydWUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBlbXB0eSBHZW9KU09OIHRpbGVcbiAgICAgICAgaWYgKCFkYXRhKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXJzID0gbmV3IEJ1ZmZlclNldChkYXRhLmJ1ZmZlcnMpO1xuICAgICAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBkYXRhLmVsZW1lbnRHcm91cHM7XG4gICAgICAgIHRoaXMudGlsZUV4dGVudCA9IGRhdGEuZXh0ZW50O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBnaXZlbiBhIGRhdGEgb2JqZWN0IGFuZCBhIEdMIHBhaW50ZXIsIGRlc3Ryb3kgYW5kIHJlLWNyZWF0ZVxuICAgICAqIGFsbCBvZiBpdHMgYnVmZmVycy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyXG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICByZWxvYWRTeW1ib2xEYXRhOiBmdW5jdGlvbihkYXRhLCBwYWludGVyKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIC8vIHRoZSB0aWxlIGhhcyBiZWVuIGRlc3Ryb3llZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5nbHlwaEVsZW1lbnQuZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25WZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcblxuICAgICAgICB2YXIgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoZGF0YS5idWZmZXJzKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4ID0gYnVmZmVycy5nbHlwaFZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoRWxlbWVudCA9IGJ1ZmZlcnMuZ2x5cGhFbGVtZW50O1xuICAgICAgICB0aGlzLmJ1ZmZlcnMuaWNvblZlcnRleCA9IGJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50ID0gYnVmZmVycy5pY29uRWxlbWVudDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmNvbGxpc2lvbkJveFZlcnRleCA9IGJ1ZmZlcnMuY29sbGlzaW9uQm94VmVydGV4O1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzW2lkXSA9IGRhdGEuZWxlbWVudEdyb3Vwc1tpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWFrZSBzdXJlIHRoYXQgdGhpcyB0aWxlIGRvZXNuJ3Qgb3duIGFueSBkYXRhIHdpdGhpbiBhIGdpdmVuXG4gICAgICogcGFpbnRlciwgc28gdGhhdCBpdCBkb2Vzbid0IGNvbnN1bWUgYW55IG1lbW9yeSBvciBtYWludGFpblxuICAgICAqIGFueSByZWZlcmVuY2VzIHRvIHRoZSBwYWludGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyIGdsIHBhaW50ZXIgb2JqZWN0XG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB1bmxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihwYWludGVyKSB7XG4gICAgICAgIGZvciAodmFyIGIgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlcnNbYl0uZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSBudWxsO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZUNvb3JkO1xuXG5mdW5jdGlvbiBUaWxlQ29vcmQoeiwgeCwgeSwgdykge1xuICAgIGlmICh3ID09PSB1bmRlZmluZWQpIHcgPSAwO1xuICAgIHRoaXMueiA9IHo7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMudyA9IHc7XG5cbiAgICAvLyBjYWxjdWxhdGUgaWRcbiAgICB3ICo9IDI7XG4gICAgaWYgKHcgPCAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB2YXIgZGltID0gMSA8PCB0aGlzLno7XG4gICAgdGhpcy5pZCA9ICgoZGltICogZGltICogdyArIGRpbSAqIHRoaXMueSArIHRoaXMueCkgKiAzMikgKyB0aGlzLno7XG59XG5cblRpbGVDb29yZC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy56ICsgXCIvXCIgKyB0aGlzLnggKyBcIi9cIiArIHRoaXMueTtcbn07XG5cbi8vIFBhcnNlIGEgcGFja2VkIGludGVnZXIgaWQgaW50byBhIFRpbGVDb29yZCBvYmplY3RcblRpbGVDb29yZC5mcm9tSUQgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciB6ID0gaWQgJSAzMiwgZGltID0gMSA8PCB6O1xuICAgIHZhciB4eSA9ICgoaWQgLSB6KSAvIDMyKTtcbiAgICB2YXIgeCA9IHh5ICUgZGltLCB5ID0gKCh4eSAtIHgpIC8gZGltKSAlIGRpbTtcbiAgICB2YXIgdyA9IE1hdGguZmxvb3IoeHkgLyAoZGltICogZGltKSk7XG4gICAgaWYgKHcgJSAyICE9PSAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB3IC89IDI7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQoeiwgeCwgeSwgdyk7XG59O1xuXG4vLyBnaXZlbiBhIGxpc3Qgb2YgdXJscywgY2hvb3NlIGEgdXJsIHRlbXBsYXRlIGFuZCByZXR1cm4gYSB0aWxlIFVSTFxuVGlsZUNvb3JkLnByb3RvdHlwZS51cmwgPSBmdW5jdGlvbih1cmxzLCBzb3VyY2VNYXhab29tKSB7XG4gICAgcmV0dXJuIHVybHNbKHRoaXMueCArIHRoaXMueSkgJSB1cmxzLmxlbmd0aF1cbiAgICAgICAgLnJlcGxhY2UoJ3twcmVmaXh9JywgKHRoaXMueCAlIDE2KS50b1N0cmluZygxNikgKyAodGhpcy55ICUgMTYpLnRvU3RyaW5nKDE2KSlcbiAgICAgICAgLnJlcGxhY2UoJ3t6fScsIE1hdGgubWluKHRoaXMueiwgc291cmNlTWF4Wm9vbSB8fCB0aGlzLnopKVxuICAgICAgICAucmVwbGFjZSgne3h9JywgdGhpcy54KVxuICAgICAgICAucmVwbGFjZSgne3l9JywgdGhpcy55KTtcbn07XG5cbi8vIFJldHVybiB0aGUgY29vcmRpbmF0ZSBvZiB0aGUgcGFyZW50IHRpbGVcblRpbGVDb29yZC5wcm90b3R5cGUucGFyZW50ID0gZnVuY3Rpb24oc291cmNlTWF4Wm9vbSkge1xuICAgIGlmICh0aGlzLnogPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgLy8gdGhlIGlkIHJlcHJlc2VudHMgYW4gb3ZlcnNjYWxlZCB0aWxlLCByZXR1cm4gdGhlIHNhbWUgY29vcmRpbmF0ZXMgd2l0aCBhIGxvd2VyIHpcbiAgICBpZiAodGhpcy56ID4gc291cmNlTWF4Wm9vbSkge1xuICAgICAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCBNYXRoLmZsb29yKHRoaXMueCAvIDIpLCBNYXRoLmZsb29yKHRoaXMueSAvIDIpLCB0aGlzLncpO1xufTtcblxuVGlsZUNvb3JkLnByb3RvdHlwZS53cmFwcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQodGhpcy56LCB0aGlzLngsIHRoaXMueSwgMCk7XG59O1xuXG4vLyBSZXR1cm4gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB0aWxlJ3MgY2hpbGRyZW5cblRpbGVDb29yZC5wcm90b3R5cGUuY2hpbGRyZW4gPSBmdW5jdGlvbihzb3VyY2VNYXhab29tKSB7XG5cbiAgICBpZiAodGhpcy56ID49IHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgLy8gcmV0dXJuIGEgc2luZ2xlIHRpbGUgY29vcmQgcmVwcmVzZW50aW5nIGEgYW4gb3ZlcnNjYWxlZCB0aWxlXG4gICAgICAgIHJldHVybiBbbmV3IFRpbGVDb29yZCh0aGlzLnogKyAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KV07XG4gICAgfVxuXG4gICAgdmFyIHogPSB0aGlzLnogKyAxO1xuICAgIHZhciB4ID0gdGhpcy54ICogMjtcbiAgICB2YXIgeSA9IHRoaXMueSAqIDI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IFRpbGVDb29yZCh6LCB4LCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHgsIHkgKyAxLCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5ICsgMSwgdGhpcy53KVxuICAgIF07XG59O1xuXG4vLyBUYWtlbiBmcm9tIHBvbHltYXBzIHNyYy9MYXllci5qc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3NpbXBsZWdlby9wb2x5bWFwcy9ibG9iL21hc3Rlci9zcmMvTGF5ZXIuanMjTDMzMy1MMzgzXG5cbmZ1bmN0aW9uIGVkZ2UoYSwgYikge1xuICAgIGlmIChhLnJvdyA+IGIucm93KSB7IHZhciB0ID0gYTsgYSA9IGI7IGIgPSB0OyB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDA6IGEuY29sdW1uLFxuICAgICAgICB5MDogYS5yb3csXG4gICAgICAgIHgxOiBiLmNvbHVtbixcbiAgICAgICAgeTE6IGIucm93LFxuICAgICAgICBkeDogYi5jb2x1bW4gLSBhLmNvbHVtbixcbiAgICAgICAgZHk6IGIucm93IC0gYS5yb3dcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBzY2FuU3BhbnMoZTAsIGUxLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciB5MCA9IE1hdGgubWF4KHltaW4sIE1hdGguZmxvb3IoZTEueTApKTtcbiAgICB2YXIgeTEgPSBNYXRoLm1pbih5bWF4LCBNYXRoLmNlaWwoZTEueTEpKTtcblxuICAgIC8vIHNvcnQgZWRnZXMgYnkgeC1jb29yZGluYXRlXG4gICAgaWYgKChlMC54MCA9PT0gZTEueDAgJiYgZTAueTAgPT09IGUxLnkwKSA/XG4gICAgICAgICAgICAoZTAueDAgKyBlMS5keSAvIGUwLmR5ICogZTAuZHggPCBlMS54MSkgOlxuICAgICAgICAgICAgKGUwLngxIC0gZTEuZHkgLyBlMC5keSAqIGUwLmR4IDwgZTEueDApKSB7XG4gICAgICAgIHZhciB0ID0gZTA7IGUwID0gZTE7IGUxID0gdDtcbiAgICB9XG5cbiAgICAvLyBzY2FuIGxpbmVzIVxuICAgIHZhciBtMCA9IGUwLmR4IC8gZTAuZHk7XG4gICAgdmFyIG0xID0gZTEuZHggLyBlMS5keTtcbiAgICB2YXIgZDAgPSBlMC5keCA+IDA7IC8vIHVzZSB5ICsgMSB0byBjb21wdXRlIHgwXG4gICAgdmFyIGQxID0gZTEuZHggPCAwOyAvLyB1c2UgeSArIDEgdG8gY29tcHV0ZSB4MVxuICAgIGZvciAodmFyIHkgPSB5MDsgeSA8IHkxOyB5KyspIHtcbiAgICAgICAgdmFyIHgwID0gbTAgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMC5keSwgeSArIGQwIC0gZTAueTApKSArIGUwLngwO1xuICAgICAgICB2YXIgeDEgPSBtMSAqIE1hdGgubWF4KDAsIE1hdGgubWluKGUxLmR5LCB5ICsgZDEgLSBlMS55MCkpICsgZTEueDA7XG4gICAgICAgIHNjYW5MaW5lKE1hdGguZmxvb3IoeDEpLCBNYXRoLmNlaWwoeDApLCB5KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNjYW5UcmlhbmdsZShhLCBiLCBjLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciBhYiA9IGVkZ2UoYSwgYiksXG4gICAgICAgIGJjID0gZWRnZShiLCBjKSxcbiAgICAgICAgY2EgPSBlZGdlKGMsIGEpO1xuXG4gICAgdmFyIHQ7XG5cbiAgICAvLyBzb3J0IGVkZ2VzIGJ5IHktbGVuZ3RoXG4gICAgaWYgKGFiLmR5ID4gYmMuZHkpIHsgdCA9IGFiOyBhYiA9IGJjOyBiYyA9IHQ7IH1cbiAgICBpZiAoYWIuZHkgPiBjYS5keSkgeyB0ID0gYWI7IGFiID0gY2E7IGNhID0gdDsgfVxuICAgIGlmIChiYy5keSA+IGNhLmR5KSB7IHQgPSBiYzsgYmMgPSBjYTsgY2EgPSB0OyB9XG5cbiAgICAvLyBzY2FuIHNwYW4hIHNjYW4gc3BhbiFcbiAgICBpZiAoYWIuZHkpIHNjYW5TcGFucyhjYSwgYWIsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbiAgICBpZiAoYmMuZHkpIHNjYW5TcGFucyhjYSwgYmMsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbn1cblxuVGlsZUNvb3JkLmNvdmVyID0gZnVuY3Rpb24oeiwgYm91bmRzLCBhY3R1YWxaKSB7XG4gICAgdmFyIHRpbGVzID0gMSA8PCB6O1xuICAgIHZhciB0ID0ge307XG5cbiAgICBmdW5jdGlvbiBzY2FuTGluZSh4MCwgeDEsIHkpIHtcbiAgICAgICAgdmFyIHgsIHd4O1xuICAgICAgICBpZiAoeSA+PSAwICYmIHkgPD0gdGlsZXMpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IHgwOyB4IDwgeDE7IHgrKykge1xuICAgICAgICAgICAgICAgIHd4ID0gKHggKyB0aWxlcykgJSB0aWxlcztcbiAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBuZXcgVGlsZUNvb3JkKGFjdHVhbFosIHd4LCB5LCBNYXRoLmZsb29yKHggLyB0aWxlcykpO1xuICAgICAgICAgICAgICAgIHRbY29vcmQuaWRdID0gY29vcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXZpZGUgdGhlIHNjcmVlbiB1cCBpbiB0d28gdHJpYW5nbGVzIGFuZCBzY2FuIGVhY2ggb2YgdGhlbTpcbiAgICAvLyArLS0tL1xuICAgIC8vIHwgLyB8XG4gICAgLy8gLy0tLStcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzBdLCBib3VuZHNbMV0sIGJvdW5kc1syXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzJdLCBib3VuZHNbM10sIGJvdW5kc1swXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0KS5tYXAoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRbaWRdO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQ2FjaGUgPSByZXF1aXJlKCcuLi91dGlsL21ydV9jYWNoZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUaWxlUHlyYW1pZDtcblxuLyoqXG4gKiBBIHRpbGUgcHlyYW1pZCBpcyBhIHNwZWNpYWxpemVkIGNhY2hlIGFuZCBkYXRhc3RydWN0dXJlXG4gKiB0aGF0IGNvbnRhaW5zIHRpbGVzLiBJdCdzIHVzZWQgYnkgc291cmNlcyB0byBtYW5hZ2UgdGhlaXJcbiAqIGRhdGEuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnRpbGVTaXplXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5taW56b29tXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5tYXh6b29tXG4gKi9cbmZ1bmN0aW9uIFRpbGVQeXJhbWlkKG9wdGlvbnMpIHtcbiAgICB0aGlzLnRpbGVTaXplID0gb3B0aW9ucy50aWxlU2l6ZTtcbiAgICB0aGlzLm1pbnpvb20gPSBvcHRpb25zLm1pbnpvb207XG4gICAgdGhpcy5tYXh6b29tID0gb3B0aW9ucy5tYXh6b29tO1xuICAgIHRoaXMucmVwYXJzZU92ZXJzY2FsZWQgPSBvcHRpb25zLnJlcGFyc2VPdmVyc2NhbGVkO1xuXG4gICAgdGhpcy5fbG9hZCA9IG9wdGlvbnMubG9hZDtcbiAgICB0aGlzLl9hYm9ydCA9IG9wdGlvbnMuYWJvcnQ7XG4gICAgdGhpcy5fdW5sb2FkID0gb3B0aW9ucy51bmxvYWQ7XG4gICAgdGhpcy5fYWRkID0gb3B0aW9ucy5hZGQ7XG4gICAgdGhpcy5fcmVtb3ZlID0gb3B0aW9ucy5yZW1vdmU7XG4gICAgdGhpcy5fcmVkb1BsYWNlbWVudCA9IG9wdGlvbnMucmVkb1BsYWNlbWVudDtcblxuICAgIHRoaXMuX3RpbGVzID0ge307XG4gICAgdGhpcy5fY2FjaGUgPSBuZXcgQ2FjaGUob3B0aW9ucy5jYWNoZVNpemUsIGZ1bmN0aW9uKHRpbGUpIHsgcmV0dXJuIHRoaXMuX3VubG9hZCh0aWxlKTsgfS5iaW5kKHRoaXMpKTtcbn1cblxuVGlsZVB5cmFtaWQucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIENvbmZpcm0gdGhhdCBldmVyeSB0cmFja2VkIHRpbGUgaXMgbG9hZGVkLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIGFsbCB0aWxlcyBhcmUgbG9hZGVkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgdCBpbiB0aGlzLl90aWxlcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl90aWxlc1t0XS5sb2FkZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRpbGUgaWRzIG9yZGVyZWQgd2l0aCB6LW9yZGVyLCBhbmQgY2FzdCB0byBudW1iZXJzXG4gICAgICogQHJldHVybnMge0FycmF5PG51bWJlcj59IGlkc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgb3JkZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl90aWxlcylcbiAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIChiICUgMzIpIC0gKGEgJSAzMik7IH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGlkKSB7IHJldHVybiAraWQ7IH0pO1xuICAgIH0sXG5cbiAgICByZW5kZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yZGVyZWRJRHMoKS5maWx0ZXIoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90aWxlc1tpZF0ubG9hZGVkICYmICF0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICByZWxvYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9jYWNoZS5yZXNldCgpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMuX3RpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2FkKHRoaXMuX3RpbGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzcGVjaWZpYyB0aWxlIGJ5IGlkXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCB0aWxlIGlkXG4gICAgICogQHJldHVybnMge09iamVjdH0gdGlsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0VGlsZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RpbGVzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogZ2V0IHRoZSB6b29tIGxldmVsIGFkanVzdGVkIGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtYXAgYW5kIHNvdXJjZSB0aWxlc2l6ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICogQHJldHVybnMge251bWJlcn0gem9vbSBsZXZlbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm0uem9vbSArIE1hdGgubG9nKHRyYW5zZm9ybS50aWxlU2l6ZSAvIHRoaXMudGlsZVNpemUpIC8gTWF0aC5MTjI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHpvb20gbGV2ZWwgdGhhdCB3aWxsIGNvdmVyIGFsbCB0aWxlcyBpbiBhIGdpdmVuIHRyYW5zZm9ybVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSB6b29tIGxldmVsXG4gICAgICovXG4gICAgY292ZXJpbmdab29tTGV2ZWw6IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldFpvb20odHJhbnNmb3JtKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgdHJhbnNmb3JtLCByZXR1cm4gYWxsIGNvb3JkaW5hdGVzIHRoYXQgY291bGQgY292ZXIgdGhhdFxuICAgICAqIHRyYW5zZm9ybSBmb3IgYSBjb3ZlcmluZyB6b29tIGxldmVsLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8VGlsZT59IHRpbGVzXG4gICAgICovXG4gICAgY292ZXJpbmdUaWxlczogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHZhciB6ID0gdGhpcy5jb3ZlcmluZ1pvb21MZXZlbCh0cmFuc2Zvcm0pO1xuICAgICAgICB2YXIgYWN0dWFsWiA9IHo7XG5cbiAgICAgICAgaWYgKHogPCB0aGlzLm1pbnpvb20pIHJldHVybiBbXTtcbiAgICAgICAgaWYgKHogPiB0aGlzLm1heHpvb20pIHogPSB0aGlzLm1heHpvb207XG5cbiAgICAgICAgdmFyIHRyID0gdHJhbnNmb3JtLFxuICAgICAgICAgICAgdGlsZUNlbnRlciA9IHRyLmxvY2F0aW9uQ29vcmRpbmF0ZSh0ci5jZW50ZXIpLl96b29tVG8oeiksXG4gICAgICAgICAgICBjZW50ZXJQb2ludCA9IG5ldyBQb2ludCh0aWxlQ2VudGVyLmNvbHVtbiAtIDAuNSwgdGlsZUNlbnRlci5yb3cgLSAwLjUpO1xuXG4gICAgICAgIHJldHVybiBUaWxlQ29vcmQuY292ZXIoeiwgW1xuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCgwLCAwKSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQodHIud2lkdGgsIDApKS5fem9vbVRvKHopLFxuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCh0ci53aWR0aCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQoMCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KVxuICAgICAgICBdLCB0aGlzLnJlcGFyc2VPdmVyc2NhbGVkID8gYWN0dWFsWiA6IHopLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGNlbnRlclBvaW50LmRpc3QoYSkgLSBjZW50ZXJQb2ludC5kaXN0KGIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmluZCBjaGlsZHJlbiBvZiB0aGUgZ2l2ZW4gdGlsZSAodXAgdG8gbWF4Q292ZXJpbmdab29tKSB0aGF0IGFyZSBhbHJlYWR5IGxvYWRlZDtcbiAgICAgKiBhZGRzIGZvdW5kIHRpbGVzIHRvIHJldGFpbiBvYmplY3Q7IHJldHVybnMgdHJ1ZSBpZiBjaGlsZHJlbiBjb21wbGV0ZWx5IGNvdmVyIHRoZSB0aWxlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENvdmVyaW5nWm9vbVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0YWluXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIG9wZXJhdGlvbiB3YXMgY29tcGxldGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRDaGlsZHJlbjogZnVuY3Rpb24oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IHRydWU7XG4gICAgICAgIHZhciB6ID0gY29vcmQuejtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGNvb3JkLmNoaWxkcmVuKHRoaXMubWF4em9vbSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBjb29yZHNbaV0uaWQ7XG4gICAgICAgICAgICBpZiAodGhpcy5fdGlsZXNbaWRdICYmIHRoaXMuX3RpbGVzW2lkXS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICByZXRhaW5baWRdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29tcGxldGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoeiA8IG1heENvdmVyaW5nWm9vbSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBHbyBmdXJ0aGVyIGRvd24gdGhlIGhpZXJhcmNoeSB0byBmaW5kIG1vcmUgdW5sb2FkZWQgY2hpbGRyZW4uXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3Jkc1tpXSwgbWF4Q292ZXJpbmdab29tLCByZXRhaW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcGxldGU7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBsb2FkZWQgcGFyZW50IG9mIHRoZSBnaXZlbiB0aWxlICh1cCB0byBtaW5Db3ZlcmluZ1pvb20pO1xuICAgICAqIGFkZHMgdGhlIGZvdW5kIHRpbGUgdG8gcmV0YWluIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgdGlsZSBpZiBmb3VuZFxuICAgICAqXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5Db3ZlcmluZ1pvb21cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJldGFpblxuICAgICAqIEByZXR1cm5zIHtUaWxlfSB0aWxlIG9iamVjdFxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRQYXJlbnQ6IGZ1bmN0aW9uKGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbikge1xuICAgICAgICBmb3IgKHZhciB6ID0gY29vcmQueiAtIDE7IHogPj0gbWluQ292ZXJpbmdab29tOyB6LS0pIHtcbiAgICAgICAgICAgIGNvb3JkID0gY29vcmQucGFyZW50KHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2Nvb3JkLmlkXTtcbiAgICAgICAgICAgIGlmICh0aWxlICYmIHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0YWluW2Nvb3JkLmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aWxlcyB0aGF0IGFyZSBvdXRzaWRlIHRoZSB2aWV3cG9ydCBhbmQgYWRkcyBuZXcgdGlsZXMgdGhhdFxuICAgICAqIGFyZSBpbnNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXNlZCwgdHJhbnNmb3JtLCBmYWRlRHVyYXRpb24pIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBjb29yZDtcbiAgICAgICAgdmFyIHRpbGU7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBvdmVyem9vbWluZy91bmRlcnpvb21pbmcgYW1vdW50cy5cbiAgICAgICAgdmFyIHpvb20gPSBNYXRoLmZsb29yKHRoaXMuZ2V0Wm9vbSh0cmFuc2Zvcm0pKTtcbiAgICAgICAgdmFyIG1pbkNvdmVyaW5nWm9vbSA9IHV0aWwuY2xhbXAoem9vbSAtIDEwLCB0aGlzLm1pbnpvb20sIHRoaXMubWF4em9vbSk7XG4gICAgICAgIHZhciBtYXhDb3ZlcmluZ1pvb20gPSB1dGlsLmNsYW1wKHpvb20gKyAxLCAgdGhpcy5taW56b29tLCB0aGlzLm1heHpvb20pO1xuXG4gICAgICAgIC8vIFJldGFpbiBpcyBhIGxpc3Qgb2YgdGlsZXMgdGhhdCB3ZSBzaG91bGRuJ3QgZGVsZXRlLCBldmVuIGlmIHRoZXkgYXJlIG5vdFxuICAgICAgICAvLyB0aGUgbW9zdCBpZGVhbCB0aWxlIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydC4gVGhpcyBtYXkgaW5jbHVkZSB0aWxlcyBsaWtlXG4gICAgICAgIC8vIHBhcmVudCBvciBjaGlsZCB0aWxlcyB0aGF0IGFyZSAqYWxyZWFkeSogbG9hZGVkLlxuICAgICAgICB2YXIgcmV0YWluID0ge307XG4gICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICAvLyBDb3ZlcmVkIGlzIGEgbGlzdCBvZiByZXRhaW5lZCB0aWxlcyB3aG8ncyBhcmVhcyBhcmUgZnVsbCBjb3ZlcmVkIGJ5IG90aGVyLFxuICAgICAgICAvLyBiZXR0ZXIsIHJldGFpbmVkIHRpbGVzLiBUaGV5IGFyZSBub3QgZHJhd24gc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fY292ZXJlZFRpbGVzID0ge307XG5cbiAgICAgICAgdmFyIHJlcXVpcmVkID0gdXNlZCA/IHRoaXMuY292ZXJpbmdUaWxlcyh0cmFuc2Zvcm0pIDogW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXF1aXJlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29vcmQgPSByZXF1aXJlZFtpXTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmFkZFRpbGUoY29vcmQpO1xuXG4gICAgICAgICAgICByZXRhaW5bY29vcmQuaWRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHRpbGUubG9hZGVkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBUaGUgdGlsZSB3ZSByZXF1aXJlIGlzIG5vdCB5ZXQgbG9hZGVkLlxuICAgICAgICAgICAgLy8gUmV0YWluIGNoaWxkIG9yIHBhcmVudCB0aWxlcyB0aGF0IGNvdmVyIHRoZSBzYW1lIGFyZWEuXG4gICAgICAgICAgICBpZiAoIXRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3JkLCBtYXhDb3ZlcmluZ1pvb20sIHJldGFpbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmRMb2FkZWRQYXJlbnQoY29vcmQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHJldGFpbikge1xuICAgICAgICAgICAgY29vcmQgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1tpZF07XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aWxlLnRpbWVBZGRlZCA+IG5vdyAtIChmYWRlRHVyYXRpb24gfHwgMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHRpbGUgaXMgc3RpbGwgZmFkaW5nIGluLiBGaW5kIHRpbGVzIHRvIGNyb3NzLWZhZGUgd2l0aCBpdC5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maW5kTG9hZGVkQ2hpbGRyZW4oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0YWluW2lkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5kTG9hZGVkUGFyZW50KGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0aWxlcyB3ZSBkb24ndCBuZWVkIGFueW1vcmUuXG4gICAgICAgIHZhciByZW1vdmUgPSB1dGlsLmtleXNEaWZmZXJlbmNlKHRoaXMuX3RpbGVzLCByZXRhaW4pO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVRpbGUoK3JlbW92ZVtpXSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgdGlsZSwgZ2l2ZW4gaXRzIGNvb3JkaW5hdGUsIHRvIHRoZSBweXJhbWlkLlxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7Q29vcmRpbmF0ZX0gdGhlIGNvb3JkaW5hdGUuXG4gICAgICovXG4gICAgYWRkVGlsZTogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl90aWxlc1tjb29yZC5pZF07XG4gICAgICAgIGlmICh0aWxlKVxuICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG5cbiAgICAgICAgdmFyIHdyYXBwZWQgPSBjb29yZC53cmFwcGVkKCk7XG4gICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1t3cmFwcGVkLmlkXTtcblxuICAgICAgICBpZiAoIXRpbGUpIHtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl9jYWNoZS5nZXQod3JhcHBlZC5pZCk7XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aGlzLl9yZWRvUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVkb1BsYWNlbWVudCh0aWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGlsZSkge1xuICAgICAgICAgICAgdmFyIHpvb20gPSBjb29yZC56O1xuICAgICAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gem9vbSA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLm1heHpvb20pIDogMTtcbiAgICAgICAgICAgIHRpbGUgPSBuZXcgVGlsZSh3cmFwcGVkLCB0aGlzLnRpbGVTaXplICogb3ZlcnNjYWxpbmcpO1xuICAgICAgICAgICAgdGhpcy5fbG9hZCh0aWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbGUudXNlcysrO1xuICAgICAgICB0aGlzLl90aWxlc1tjb29yZC5pZF0gPSB0aWxlO1xuICAgICAgICB0aGlzLl9hZGQodGlsZSwgY29vcmQpO1xuXG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSB0aWxlLCBnaXZlbiBpdHMgaWQsIGZyb20gdGhlIHB5cmFtaWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIHRpbGUgaWRcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBub3RoaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICByZW1vdmVUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2lkXTtcbiAgICAgICAgaWYgKCF0aWxlKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRpbGUudXNlcy0tO1xuICAgICAgICBkZWxldGUgdGhpcy5fdGlsZXNbaWRdO1xuICAgICAgICB0aGlzLl9yZW1vdmUodGlsZSk7XG5cbiAgICAgICAgaWYgKHRpbGUudXNlcyA+IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZS5hZGQodGlsZS5jb29yZC53cmFwcGVkKCkuaWQsIHRpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fYWJvcnQodGlsZSk7XG4gICAgICAgICAgICB0aGlzLl91bmxvYWQodGlsZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCB0aWxlcyBmcm9tIHRoaXMgcHlyYW1pZFxuICAgICAqL1xuICAgIGNsZWFyVGlsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBpZCBpbiB0aGlzLl90aWxlcylcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlVGlsZShpZCk7XG4gICAgICAgIHRoaXMuX2NhY2hlLnJlc2V0KCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZvciBhIGdpdmVuIGNvb3JkaW5hdGUsIHNlYXJjaCB0aHJvdWdoIG91ciBjdXJyZW50IHRpbGVzIGFuZCBhdHRlbXB0XG4gICAgICogdG8gZmluZCBhIHRpbGUgYXQgdGhhdCBwb2ludFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSB0aWxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aWxlQXQ6IGZ1bmN0aW9uKGNvb3JkKSB7XG4gICAgICAgIHZhciBpZHMgPSB0aGlzLm9yZGVyZWRJRHMoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gdGhpcy5fdGlsZXNbaWRzW2ldXTtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aWxlLnBvc2l0aW9uQXQoY29vcmQsIHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICBpZiAocG9zICYmIHBvcy54ID49IDAgJiYgcG9zLnggPCA0MDk2ICYmIHBvcy55ID49IDAgJiYgcG9zLnkgPCA0MDk2KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGNsaWNrIGlzIHdpdGhpbiB0aGUgdmlld3BvcnQuIFRoZXJlIGlzIG9ubHkgZXZlciBvbmUgdGlsZSBpblxuICAgICAgICAgICAgICAgIC8vIGEgbGF5ZXIgdGhhdCBoYXMgdGhpcyBwcm9wZXJ0eS5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB0aWxlOiB0aWxlLFxuICAgICAgICAgICAgICAgICAgICB4OiBwb3MueCxcbiAgICAgICAgICAgICAgICAgICAgeTogcG9zLnksXG4gICAgICAgICAgICAgICAgICAgIHNjYWxlOiBwb3Muc2NhbGVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlU291cmNlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlU291cmNlKG9wdGlvbnMpIHtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLCB1dGlsLnBpY2sob3B0aW9ucywgWyd1cmwnLCAndGlsZVNpemUnXSkpO1xuXG4gICAgaWYgKHRoaXMudGlsZVNpemUgIT09IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyJyk7XG4gICAgfVxuXG4gICAgU291cmNlLl9sb2FkVGlsZUpTT04uY2FsbCh0aGlzLCBvcHRpb25zKTtcbn1cblxuVmVjdG9yVGlsZVNvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIG1pbnpvb206IDAsXG4gICAgbWF4em9vbTogMjIsXG4gICAgdGlsZVNpemU6IDUxMixcbiAgICByZXBhcnNlT3ZlcnNjYWxlZDogdHJ1ZSxcbiAgICBfbG9hZGVkOiBmYWxzZSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9weXJhbWlkICYmIHRoaXMuX3B5cmFtaWQubG9hZGVkKCk7XG4gICAgfSxcblxuICAgIHVwZGF0ZTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIGlmICh0aGlzLl9weXJhbWlkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVkb1BsYWNlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fcHlyYW1pZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQub3JkZXJlZElEcygpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl9weXJhbWlkLmdldFRpbGUoaWRzW2ldKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcbiAgICBmZWF0dXJlc0F0OiBTb3VyY2UuX3ZlY3RvckZlYXR1cmVzQXQsXG5cbiAgICBfbG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gdGlsZS5jb29yZC56ID4gdGhpcy5tYXh6b29tID8gTWF0aC5wb3coMiwgdGlsZS5jb29yZC56IC0gdGhpcy5tYXh6b29tKSA6IDE7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICB1cmw6IHRpbGUuY29vcmQudXJsKHRoaXMudGlsZXMsIHRoaXMubWF4em9vbSksXG4gICAgICAgICAgICB1aWQ6IHRpbGUudWlkLFxuICAgICAgICAgICAgY29vcmQ6IHRpbGUuY29vcmQsXG4gICAgICAgICAgICB6b29tOiB0aWxlLmNvb3JkLnosXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb20sXG4gICAgICAgICAgICB0aWxlU2l6ZTogdGhpcy50aWxlU2l6ZSAqIG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgc291cmNlOiB0aGlzLmlkLFxuICAgICAgICAgICAgb3ZlcnNjYWxpbmc6IG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgYW5nbGU6IHRoaXMubWFwLnRyYW5zZm9ybS5hbmdsZSxcbiAgICAgICAgICAgIHBpdGNoOiB0aGlzLm1hcC50cmFuc2Zvcm0ucGl0Y2gsXG4gICAgICAgICAgICBjb2xsaXNpb25EZWJ1ZzogdGhpcy5tYXAuY29sbGlzaW9uRGVidWdcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGlsZS53b3JrZXJJRCkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbG9hZCB0aWxlJywgcGFyYW1zLCB0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcywgdGlsZSksIHRpbGUud29ya2VySUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIHRpbGUnLCBwYXJhbXMsIHRoaXMuX3RpbGVMb2FkZWQuYmluZCh0aGlzLCB0aWxlKSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX3RpbGVMb2FkZWQ6IGZ1bmN0aW9uKHRpbGUsIGVyciwgZGF0YSkge1xuICAgICAgICBpZiAodGlsZS5hYm9ydGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5lcnJvcicsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLmxvYWRWZWN0b3JEYXRhKGRhdGEpO1xuXG4gICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgdGlsZS5yZWRvV2hlbkRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdhYm9ydCB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9yZWRvVGlsZVBsYWNlbWVudDogZnVuY3Rpb24odGlsZSkge1xuXG4gICAgICAgIGlmICghdGlsZS5sb2FkZWQgfHwgdGlsZS5yZWRvaW5nUGxhY2VtZW50KSB7XG4gICAgICAgICAgICB0aWxlLnJlZG9XaGVuRG9uZSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdyZWRvIHBsYWNlbWVudCcsIHtcbiAgICAgICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBhbmdsZTogdGhpcy5tYXAudHJhbnNmb3JtLmFuZ2xlLFxuICAgICAgICAgICAgcGl0Y2g6IHRoaXMubWFwLnRyYW5zZm9ybS5waXRjaCxcbiAgICAgICAgICAgIGNvbGxpc2lvbkRlYnVnOiB0aGlzLm1hcC5jb2xsaXNpb25EZWJ1Z1xuICAgICAgICB9LCBkb25lLmJpbmQodGhpcyksIHRpbGUud29ya2VySUQpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGRvbmUoXywgZGF0YSkge1xuICAgICAgICAgICAgdGlsZS5yZWxvYWRTeW1ib2xEYXRhKGRhdGEsIHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuXG4gICAgICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICAgICAgICAgIHRpbGUucmVkb1doZW5Eb25lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuLi9nZW8vY29vcmRpbmF0ZScpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWaWRlb1NvdXJjZTtcblxuLyoqXG4gKiBDcmVhdGUgYSBWaWRlbyBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICogQGNsYXNzIFZpZGVvU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge1N0cmluZ3xBcnJheX0gb3B0aW9ucy51cmwgQSBzdHJpbmcgb3IgYXJyYXkgb2YgVVJMKHMpIHRvIHZpZGVvIGZpbGVzXG4gKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLmNvb3JkaW5hdGVzIGxhdCxsbmcgY29vcmRpbmF0ZXMgaW4gb3JkZXIgY2xvY2t3aXNlIHN0YXJ0aW5nIGF0IHRoZSB0b3AgbGVmdDogdGwsIHRyLCBiciwgYmxcbiAqIEBleGFtcGxlXG4gKiB2YXIgc291cmNlT2JqID0gbmV3IG1hcGJveGdsLlZpZGVvU291cmNlKHtcbiAqICAgIHVybDogW1xuICogICAgICAgICdodHRwczovL3d3dy5tYXBib3guY29tL3ZpZGVvcy9iYWx0aW1vcmUtc21va2UubXA0JyxcbiAqICAgICAgICAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS92aWRlb3MvYmFsdGltb3JlLXNtb2tlLndlYm0nXG4gKiAgICBdLFxuICogICAgY29vcmRpbmF0ZXM6IFtcbiAqICAgICAgICBbMzkuMTg1Nzk5MDcyMjk3NDgsIC03Ni41NDMzNTczNzIyODM5NF0sXG4gKiAgICAgICAgWzM5LjE4MzgzNjQ4NDc1ODcsIC03Ni41MjgwMzY1OTQzOTA4N10sXG4gKiAgICAgICAgWzM5LjE3NjgzMzkyNTA3NjA2LCAtNzYuNTI5NTM4NjMxNDM5Ml0sXG4gKiAgICAgICAgWzM5LjE3ODc2MzQ0MTA2NjQyLCAtNzYuNTQ1MjAyNzMyMDg2MThdXG4gKiAgICBdXG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBWaWRlb1NvdXJjZShvcHRpb25zKSB7XG4gICAgdGhpcy5jb29yZGluYXRlcyA9IG9wdGlvbnMuY29vcmRpbmF0ZXM7XG5cbiAgICBhamF4LmdldFZpZGVvKG9wdGlvbnMudXJsLCBmdW5jdGlvbihlcnIsIHZpZGVvKSB7XG4gICAgICAgIC8vIEBUT0RPIGhhbmRsZSBlcnJvcnMgdmlhIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy52aWRlbyA9IHZpZGVvO1xuICAgICAgICB0aGlzLnZpZGVvLmxvb3AgPSB0cnVlO1xuXG4gICAgICAgIHZhciBsb29wSUQ7XG5cbiAgICAgICAgLy8gc3RhcnQgcmVwYWludGluZyB3aGVuIHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gICAgICAgIHRoaXMudmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheWluZycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbG9vcElEID0gdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoSW5maW5pdHkpO1xuICAgICAgICAgICAgdGhpcy5tYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gc3RvcCByZXBhaW50aW5nIHdoZW4gdmlkZW8gc3RvcHNcbiAgICAgICAgdGhpcy52aWRlby5hZGRFdmVudExpc3RlbmVyKCdwYXVzZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5jYW5jZWwobG9vcElEKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcCkge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJyk7XG4gICAgICAgIH1cbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgSFRNTCB2aWRlbyBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRWaWRlbzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvO1xuICAgIH0sXG5cbiAgICBvbkFkZDogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMubWFwID0gbWFwO1xuICAgICAgICBpZiAodGhpcy52aWRlbykge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogQ2FsY3VsYXRlIHdoaWNoIG1lcmNhdG9yIHRpbGUgaXMgc3VpdGFibGUgZm9yIHJlbmRlcmluZyB0aGUgdmlkZW8gaW5cbiAgICAgICAgICogYW5kIGNyZWF0ZSBhIGJ1ZmZlciB3aXRoIHRoZSBjb3JuZXIgY29vcmRpbmF0ZXMuIFRoZXNlIGNvb3JkaW5hdGVzXG4gICAgICAgICAqIG1heSBiZSBvdXRzaWRlIHRoZSB0aWxlLCBiZWNhdXNlIHJhc3RlciB0aWxlcyBhcmVuJ3QgY2xpcHBlZCB3aGVuIHJlbmRlcmluZy5cbiAgICAgICAgICovXG4gICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcbiAgICAgICAgdmFyIGNvb3JkcyA9IHRoaXMuY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uKGxhdGxuZykge1xuICAgICAgICAgICAgdmFyIGxvYyA9IExhdExuZy5jb252ZXJ0KGxhdGxuZyk7XG4gICAgICAgICAgICByZXR1cm4gbWFwLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUobG9jKS56b29tVG8oMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtaW5YID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtaW5ZID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtYXhYID0gLUluZmluaXR5O1xuICAgICAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGR4ID0gbWF4WCAtIG1pblg7XG4gICAgICAgIHZhciBkeSA9IG1heFkgLSBtaW5ZO1xuICAgICAgICB2YXIgZE1heCA9IE1hdGgubWF4KGR4LCBkeSk7XG4gICAgICAgIHZhciBjZW50ZXIgPSBuZXcgQ29vcmRpbmF0ZSgobWluWCArIG1heFgpIC8gMiwgKG1pblkgKyBtYXhZKSAvIDIsIDApXG4gICAgICAgICAgICAuem9vbVRvKE1hdGguZmxvb3IoLU1hdGgubG9nKGRNYXgpIC8gTWF0aC5MTjIpKTtcblxuICAgICAgICB2YXIgdGlsZUV4dGVudCA9IDQwOTY7XG4gICAgICAgIHZhciB0aWxlQ29vcmRzID0gY29vcmRzLm1hcChmdW5jdGlvbihjb29yZCkge1xuICAgICAgICAgICAgdmFyIHpvb21lZENvb3JkID0gY29vcmQuem9vbVRvKGNlbnRlci56b29tKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZCgoem9vbWVkQ29vcmQuY29sdW1uIC0gY2VudGVyLmNvbHVtbikgKiB0aWxlRXh0ZW50KSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKCh6b29tZWRDb29yZC5yb3cgLSBjZW50ZXIucm93KSAqIHRpbGVFeHRlbnQpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGdsID0gbWFwLnBhaW50ZXIuZ2w7XG4gICAgICAgIHZhciBtYXhJbnQxNiA9IDMyNzY3O1xuICAgICAgICB2YXIgYXJyYXkgPSBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICB0aWxlQ29vcmRzWzBdLngsIHRpbGVDb29yZHNbMF0ueSwgMCwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMV0ueCwgdGlsZUNvb3Jkc1sxXS55LCBtYXhJbnQxNiwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbM10ueCwgdGlsZUNvb3Jkc1szXS55LCAwLCBtYXhJbnQxNixcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMl0ueCwgdGlsZUNvb3Jkc1syXS55LCBtYXhJbnQxNiwgbWF4SW50MTZcbiAgICAgICAgXSk7XG5cbiAgICAgICAgdGhpcy50aWxlID0gbmV3IFRpbGUoKTtcbiAgICAgICAgdGhpcy50aWxlLmJ1Y2tldHMgPSB7fTtcblxuICAgICAgICB0aGlzLnRpbGUuYm91bmRzQnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGUuYm91bmRzQnVmZmVyKTtcbiAgICAgICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGFycmF5LCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgdGhpcy5jZW50ZXIgPSBjZW50ZXI7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvICYmIHRoaXMudmlkZW8ucmVhZHlTdGF0ZSA+PSAyO1xuICAgIH0sXG5cbiAgICB1cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBub29wXG4gICAgfSxcblxuICAgIHJlbmRlcjogZnVuY3Rpb24obGF5ZXJzLCBwYWludGVyKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnZpZGVvLnJlYWR5U3RhdGUgPCAyKSByZXR1cm47IC8vIG5vdCBlbm91Z2ggZGF0YSBmb3IgY3VycmVudCBwb3NpdGlvblxuXG4gICAgICAgIHZhciBjID0gdGhpcy5jZW50ZXI7XG4gICAgICAgIHRoaXMudGlsZS5jYWxjdWxhdGVNYXRyaWNlcyhjLnpvb20sIGMuY29sdW1uLCBjLnJvdywgdGhpcy5tYXAudHJhbnNmb3JtLCBwYWludGVyKTtcblxuICAgICAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuICAgICAgICBpZiAoIXRoaXMudGlsZS50ZXh0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLnRpbGUudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLnZpZGVvKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy52aWRlbyk7XG4gICAgICAgIH1cblxuICAgICAgICBwYWludGVyLmRyYXdMYXllcnMobGF5ZXJzLCB0aGlzLnRpbGUucG9zTWF0cml4LCB0aGlzLnRpbGUpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihwb2ludCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQWN0b3IgPSByZXF1aXJlKCcuLi91dGlsL2FjdG9yJyk7XG52YXIgV29ya2VyVGlsZSA9IHJlcXVpcmUoJy4vd29ya2VyX3RpbGUnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIHZ0ID0gcmVxdWlyZSgndmVjdG9yLXRpbGUnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG52YXIgZ2VvanNvbnZ0ID0gcmVxdWlyZSgnZ2VvanNvbi12dCcpO1xudmFyIEdlb0pTT05XcmFwcGVyID0gcmVxdWlyZSgnLi9nZW9qc29uX3dyYXBwZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWxmKSB7XG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoc2VsZik7XG59O1xuXG5mdW5jdGlvbiBXb3JrZXIoc2VsZikge1xuICAgIHRoaXMuc2VsZiA9IHNlbGY7XG4gICAgdGhpcy5hY3RvciA9IG5ldyBBY3RvcihzZWxmLCB0aGlzKTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcblxuICAgIHRoaXMubG9hZGVkID0ge307XG4gICAgdGhpcy5sYXllcnMgPSBbXTtcbiAgICB0aGlzLmdlb0pTT05JbmRleGVzID0ge307XG59XG5cbnV0aWwuZXh0ZW5kKFdvcmtlci5wcm90b3R5cGUsIHtcbiAgICAnc2V0IGxheWVycyc6IGZ1bmN0aW9uKGxheWVycykge1xuICAgICAgICB0aGlzLmxheWVycyA9IGxheWVycztcbiAgICB9LFxuXG4gICAgJ2xvYWQgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHBhcmFtcy5zb3VyY2UsXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmICghdGhpcy5sb2FkaW5nW3NvdXJjZV0pXG4gICAgICAgICAgICB0aGlzLmxvYWRpbmdbc291cmNlXSA9IHt9O1xuXG5cbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLmxvYWRpbmdbc291cmNlXVt1aWRdID0gbmV3IFdvcmtlclRpbGUocGFyYW1zKTtcblxuICAgICAgICB0aWxlLnhociA9IGFqYXguZ2V0QXJyYXlCdWZmZXIocGFyYW1zLnVybCwgZG9uZS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBmdW5jdGlvbiBkb25lKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9hZGluZ1tzb3VyY2VdW3VpZF07XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgICAgICB0aWxlLmRhdGEgPSBuZXcgdnQuVmVjdG9yVGlsZShuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIHRpbGUucGFyc2UodGlsZS5kYXRhLCB0aGlzLmxheWVycywgdGhpcy5hY3RvciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRlZFtzb3VyY2VdID0gdGhpcy5sb2FkZWRbc291cmNlXSB8fCB7fTtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bdWlkXSA9IHRpbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbG9hZCB0aWxlJzogZnVuY3Rpb24ocGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgbG9hZGVkID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGVkICYmIGxvYWRlZFt1aWRdKSB7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IGxvYWRlZFt1aWRdO1xuICAgICAgICAgICAgdGlsZS5wYXJzZSh0aWxlLmRhdGEsIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2Fib3J0IHRpbGUnOiBmdW5jdGlvbihwYXJhbXMpIHtcbiAgICAgICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGluZyAmJiBsb2FkaW5nW3VpZF0pIHtcbiAgICAgICAgICAgIGxvYWRpbmdbdWlkXS54aHIuYWJvcnQoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkaW5nW3VpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbW92ZSB0aWxlJzogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIHVpZCA9IHBhcmFtcy51aWQ7XG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkZWRbdWlkXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAncmVkbyBwbGFjZW1lbnQnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gbG9hZGVkW3VpZF07XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGlsZS5yZWRvUGxhY2VtZW50KHBhcmFtcy5hbmdsZSwgcGFyYW1zLnBpdGNoLCBwYXJhbXMuY29sbGlzaW9uRGVidWcpO1xuXG4gICAgICAgICAgICBpZiAocmVzdWx0LnJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdC5yZXN1bHQsIHJlc3VsdC50cmFuc2ZlcmFibGVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2UgaWYgKGxvYWRpbmcgJiYgbG9hZGluZ1t1aWRdKSB7XG4gICAgICAgICAgICBsb2FkaW5nW3VpZF0uYW5nbGUgPSBwYXJhbXMuYW5nbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3BhcnNlIGdlb2pzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBpbmRleERhdGEgPSBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgdGhpcy5nZW9KU09OSW5kZXhlc1twYXJhbXMuc291cmNlXSA9IGdlb2pzb252dChkYXRhLCB7YmFzZVpvb206IHBhcmFtcy5tYXhab29tfSk7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIC8vIFRPRE8gYWNjZXB0IHBhcmFtcy51cmwgZm9yIHVybHMgaW5zdGVhZFxuXG4gICAgICAgIC8vIE5vdCwgYmVjYXVzZSBvZiBzYW1lIG9yaWdpbiBpc3N1ZXMsIHVybHMgbXVzdCBlaXRoZXIgaW5jbHVkZSBhblxuICAgICAgICAvLyBleHBsaWNpdCBvcmlnaW4gb3IgYWJzb2x1dGUgcGF0aC5cbiAgICAgICAgLy8gaWU6IC9mb28vYmFyLmpzb24gb3IgaHR0cDovL2V4YW1wbGUuY29tL2Jhci5qc29uXG4gICAgICAgIC8vIGJ1dCBub3QgLi4vZm9vL2Jhci5qc29uXG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zLmRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBhamF4LmdldEpTT04ocGFyYW1zLmRhdGEsIGluZGV4RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpbmRleERhdGEobnVsbCwgcGFyYW1zLmRhdGEpO1xuICAgIH0sXG5cbiAgICAnbG9hZCBnZW9qc29uIHRpbGUnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwYXJhbXMuc291cmNlLFxuICAgICAgICAgICAgY29vcmQgPSBwYXJhbXMuY29vcmQ7XG5cbiAgICAgICAgLy8gY29uc29sZS50aW1lKCd0aWxlICcgKyBjb29yZC56ICsgJyAnICsgY29vcmQueCArICcgJyArIGNvb3JkLnkpO1xuXG4gICAgICAgIHZhciBnZW9KU09OVGlsZSA9IHRoaXMuZ2VvSlNPTkluZGV4ZXNbc291cmNlXS5nZXRUaWxlKGNvb3JkLnosIGNvb3JkLngsIGNvb3JkLnkpO1xuXG4gICAgICAgIC8vIGNvbnNvbGUudGltZUVuZCgndGlsZSAnICsgY29vcmQueiArICcgJyArIGNvb3JkLnggKyAnICcgKyBjb29yZC55KTtcblxuICAgICAgICAvLyBpZiAoIWdlb0pTT05UaWxlKSBjb25zb2xlLmxvZygnbm90IGZvdW5kJywgdGhpcy5nZW9KU09OSW5kZXhlc1tzb3VyY2VdLCBjb29yZCk7XG5cbiAgICAgICAgaWYgKCFnZW9KU09OVGlsZSkgcmV0dXJuIGNhbGxiYWNrKG51bGwsIG51bGwpOyAvLyBub3RoaW5nIGluIHRoZSBnaXZlbiB0aWxlXG5cbiAgICAgICAgdmFyIHRpbGUgPSBuZXcgV29ya2VyVGlsZShwYXJhbXMpO1xuICAgICAgICB0aWxlLnBhcnNlKG5ldyBHZW9KU09OV3JhcHBlcihnZW9KU09OVGlsZS5mZWF0dXJlcyksIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG5cbiAgICAgICAgdGhpcy5sb2FkZWRbc291cmNlXSA9IHRoaXMubG9hZGVkW3NvdXJjZV0gfHwge307XG4gICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bcGFyYW1zLnVpZF0gPSB0aWxlO1xuICAgIH0sXG5cbiAgICAncXVlcnkgZmVhdHVyZXMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB0aWxlID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0gJiYgdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV1bcGFyYW1zLnVpZF07XG4gICAgICAgIGlmICh0aWxlKSB7XG4gICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLnF1ZXJ5KHBhcmFtcywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgW10pO1xuICAgICAgICB9XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBGZWF0dXJlVHJlZSA9IHJlcXVpcmUoJy4uL2RhdGEvZmVhdHVyZV90cmVlJyk7XG52YXIgQ29sbGlzaW9uID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl90aWxlJyk7XG52YXIgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyX3NldCcpO1xudmFyIGNyZWF0ZUJ1Y2tldCA9IHJlcXVpcmUoJy4uL2RhdGEvY3JlYXRlX2J1Y2tldCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlclRpbGU7XG5cbmZ1bmN0aW9uIFdvcmtlclRpbGUocGFyYW1zKSB7XG4gICAgdGhpcy5jb29yZCA9IHBhcmFtcy5jb29yZDtcbiAgICB0aGlzLnVpZCA9IHBhcmFtcy51aWQ7XG4gICAgdGhpcy56b29tID0gcGFyYW1zLnpvb207XG4gICAgdGhpcy5tYXhab29tID0gcGFyYW1zLm1heFpvb207XG4gICAgdGhpcy50aWxlU2l6ZSA9IHBhcmFtcy50aWxlU2l6ZTtcbiAgICB0aGlzLnNvdXJjZSA9IHBhcmFtcy5zb3VyY2U7XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IHBhcmFtcy5vdmVyc2NhbGluZztcbiAgICB0aGlzLmFuZ2xlID0gcGFyYW1zLmFuZ2xlO1xuICAgIHRoaXMucGl0Y2ggPSBwYXJhbXMucGl0Y2g7XG4gICAgdGhpcy5jb2xsaXNpb25EZWJ1ZyA9IHBhcmFtcy5jb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3RhY2tzID0ge307XG59XG5cbldvcmtlclRpbGUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oZGF0YSwgbGF5ZXJzLCBhY3RvciwgY2FsbGJhY2spIHtcblxuICAgIHRoaXMuc3RhdHVzID0gJ3BhcnNpbmcnO1xuXG4gICAgdGhpcy5mZWF0dXJlVHJlZSA9IG5ldyBGZWF0dXJlVHJlZSh0aGlzLmNvb3JkLCB0aGlzLm92ZXJzY2FsaW5nKTtcblxuICAgIHZhciBpLCBrLFxuICAgICAgICB0aWxlID0gdGhpcyxcbiAgICAgICAgbGF5ZXIsXG4gICAgICAgIGJ1Y2tldCxcbiAgICAgICAgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoKSxcbiAgICAgICAgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb24gPSBuZXcgQ29sbGlzaW9uKHRoaXMuem9vbSwgNDA5NiwgdGhpcy50aWxlU2l6ZSksXG4gICAgICAgIGJ1Y2tldHMgPSB7fSxcbiAgICAgICAgYnVja2V0c0luT3JkZXIgPSB0aGlzLmJ1Y2tldHNJbk9yZGVyID0gW10sXG4gICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyID0ge307XG5cbiAgICBjb2xsaXNpb24ucmVzZXQodGhpcy5hbmdsZSwgdGhpcy5waXRjaCk7XG5cbiAgICAvLyBNYXAgbm9uLXJlZiBsYXllcnMgdG8gYnVja2V0cy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKGxheWVyLnJlZilcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBtaW56b29tID0gbGF5ZXIubWluem9vbTtcbiAgICAgICAgaWYgKG1pbnpvb20gJiYgdGhpcy56b29tIDwgbWluem9vbSAmJiBtaW56b29tIDwgdGhpcy5tYXhab29tKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIG1heHpvb20gPSBsYXllci5tYXh6b29tO1xuICAgICAgICBpZiAobWF4em9vbSAmJiB0aGlzLnpvb20gPj0gbWF4em9vbSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2aXNpYmlsaXR5ID0gbGF5ZXIubGF5b3V0LnZpc2liaWxpdHk7XG4gICAgICAgIGlmICh2aXNpYmlsaXR5ID09PSAnbm9uZScpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgdGhpcy56b29tLCB0aGlzLm92ZXJzY2FsaW5nLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbiAgICAgICAgYnVja2V0LmxheWVycyA9IFtsYXllci5pZF07XG5cbiAgICAgICAgYnVja2V0c1tidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICBidWNrZXRzSW5PcmRlci5wdXNoKGJ1Y2tldCk7XG5cbiAgICAgICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgICAgICB2YXIgc291cmNlTGF5ZXIgPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXSlcbiAgICAgICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltzb3VyY2VMYXllcl0gPSB7fTtcbiAgICAgICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXVtidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZ2VvanNvbiB0aWxlXG4gICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5kZXggcmVmIGxheWVycy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKCFsYXllci5yZWYpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBidWNrZXRzW2xheWVyLnJlZl07XG4gICAgICAgIGlmICghYnVja2V0KVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgYnVja2V0LmxheWVycy5wdXNoKGxheWVyLmlkKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0ZW50ID0gNDA5NjtcblxuICAgIC8vIHJlYWQgZWFjaCBsYXllciwgYW5kIHNvcnQgaXRzIGZlYXR1cmVzIGludG8gYnVja2V0c1xuICAgIGlmIChkYXRhLmxheWVycykge1xuICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgIGZvciAoayBpbiBidWNrZXRzQnlTb3VyY2VMYXllcikge1xuICAgICAgICAgICAgbGF5ZXIgPSBkYXRhLmxheWVyc1trXTtcbiAgICAgICAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGxheWVyLmV4dGVudCkgZXh0ZW50ID0gbGF5ZXIuZXh0ZW50O1xuICAgICAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMobGF5ZXIsIGJ1Y2tldHNCeVNvdXJjZUxheWVyW2tdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdlb2pzb25cbiAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMoZGF0YSwgYnVja2V0c0J5U291cmNlTGF5ZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNvcnRMYXllckludG9CdWNrZXRzKGxheWVyLCBidWNrZXRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBmZWF0dXJlID0gbGF5ZXIuZmVhdHVyZShpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBidWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0LmZpbHRlcihmZWF0dXJlKSkge1xuICAgICAgICAgICAgICAgICAgICBidWNrZXQuZmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcHJldlBsYWNlbWVudEJ1Y2tldDtcbiAgICB2YXIgcmVtYWluaW5nID0gYnVja2V0c0luT3JkZXIubGVuZ3RoO1xuXG4gICAgLypcbiAgICAgKiAgVGhlIGFzeW5jIHBhcnNpbmcgaGVyZSBpcyBhIGJpdCB0cmlja3kuXG4gICAgICogIFNvbWUgYnVja2V0cyBkZXBlbmQgb24gcmVzb3VyY2VzIHRoYXQgbWF5IG5lZWQgdG8gYmUgbG9hZGVkIGFzeW5jIChnbHlwaHMpLlxuICAgICAqICBTb21lIGJ1Y2tldHMgbmVlZCB0byBiZSBwYXJzZWQgaW4gb3JkZXIgKHRvIGdldCBjb2xsaXNpb24gcHJpb3JpdGllcyByaWdodCkuXG4gICAgICpcbiAgICAgKiAgRGVwZW5kZW5jaWVzIGNhbGxzIGFyZSBpbml0aWF0ZWQgZmlyc3QgdG8gZ2V0IHRob3NlIHJvbGxpbmcuXG4gICAgICogIEJ1Y2tldHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlciwgYXJlbid0IHRvIHNhdmUgdGltZS5cbiAgICAgKi9cblxuICAgIGZvciAoaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWNrZXQgPSBidWNrZXRzSW5PcmRlcltpXTtcblxuICAgICAgICAvLyBMaW5rIGJ1Y2tldHMgdGhhdCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlclxuICAgICAgICBpZiAoYnVja2V0LmNvbGxpc2lvbikge1xuICAgICAgICAgICAgaWYgKHByZXZQbGFjZW1lbnRCdWNrZXQpIHtcbiAgICAgICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0Lm5leHQgPSBidWNrZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Y2tldC5wcmV2aW91c1BsYWNlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0ID0gYnVja2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5nZXREZXBlbmRlbmNpZXModGhpcywgYWN0b3IsIGRlcGVuZGVuY2llc0RvbmUoYnVja2V0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbW1lZGlhdGVseSBwYXJzZSBidWNrZXRzIHdoZXJlIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGFuZCBubyBkZXBlbmRlbmNpZXNcbiAgICAgICAgaWYgKCFidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQuZ2V0RGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVwZW5kZW5jaWVzRG9uZShidWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgYnVja2V0LmRlcGVuZGVuY2llc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQsIGVycik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VCdWNrZXQodGlsZSwgYnVja2V0LCBza2lwKSB7XG4gICAgICAgIGlmIChidWNrZXQuZ2V0RGVwZW5kZW5jaWVzICYmICFidWNrZXQuZGVwZW5kZW5jaWVzTG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmIChidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQucHJldmlvdXNQbGFjZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoIXNraXApIHtcbiAgICAgICAgICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5mZWF0dXJlcy5sZW5ndGgpIGJ1Y2tldC5hZGRGZWF0dXJlcygpO1xuICAgICAgICAgICAgdmFyIHRpbWUgPSBEYXRlLm5vdygpIC0gbm93O1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0LmZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmZWF0dXJlID0gYnVja2V0LmZlYXR1cmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLmluc2VydChmZWF0dXJlLmJib3goKSwgYnVja2V0LmxheWVycywgZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMgPSBzZWxmLmJ1Y2tldFN0YXRzIHx8IHtfdG90YWw6IDB9O1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMuX3RvdGFsICs9IHRpbWU7XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0c1tidWNrZXQuaWRdID0gKHNlbGYuYnVja2V0U3RhdHNbYnVja2V0LmlkXSB8fCAwKSArIHRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZW1haW5pbmctLTtcblxuICAgICAgICBpZiAoIXJlbWFpbmluZykge1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJ5IHBhcnNpbmcgdGhlIG5leHQgYnVja2V0LCBpZiBpdCBpcyByZWFkeVxuICAgICAgICBpZiAoYnVja2V0Lm5leHQpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5uZXh0LnByZXZpb3VzUGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldC5uZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbmUoKSB7XG5cbiAgICAgICAgdGlsZS5zdGF0dXMgPSAnZG9uZSc7XG5cbiAgICAgICAgaWYgKHRpbGUucmVkb1BsYWNlbWVudEFmdGVyRG9uZSkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRpbGUucmVkb1BsYWNlbWVudCh0aWxlLmFuZ2xlLCB0aWxlLnBpdGNoKS5yZXN1bHQ7XG4gICAgICAgICAgICBidWZmZXJzLmdseXBoVmVydGV4ID0gcmVzdWx0LmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgICAgICBidWZmZXJzLmljb25WZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5pY29uVmVydGV4O1xuICAgICAgICAgICAgYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhbnNmZXJhYmxlcyA9IFtdLFxuICAgICAgICAgICAgZWxlbWVudEdyb3VwcyA9IHt9O1xuXG4gICAgICAgIGZvciAoayBpbiBidWZmZXJzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlcmFibGVzLnB1c2goYnVmZmVyc1trXS5hcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGsgaW4gYnVja2V0cykge1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1trXSA9IGJ1Y2tldHNba10uZWxlbWVudEdyb3VwcztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cHM6IGVsZW1lbnRHcm91cHMsXG4gICAgICAgICAgICBidWZmZXJzOiBidWZmZXJzLFxuICAgICAgICAgICAgZXh0ZW50OiBleHRlbnRcbiAgICAgICAgfSwgdHJhbnNmZXJhYmxlcyk7XG4gICAgfVxufTtcblxuV29ya2VyVGlsZS5wcm90b3R5cGUucmVkb1BsYWNlbWVudCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCwgY29sbGlzaW9uRGVidWcpIHtcblxuICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gJ2RvbmUnKSB7XG4gICAgICAgIHRoaXMucmVkb1BsYWNlbWVudEFmdGVyRG9uZSA9IHRydWU7XG4gICAgICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHZhciBidWZmZXJzID0gbmV3IEJ1ZmZlclNldCgpO1xuICAgIHZhciB0cmFuc2ZlcmFibGVzID0gW107XG4gICAgdmFyIGVsZW1lbnRHcm91cHMgPSB7fTtcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICBjb2xsaXNpb24ucmVzZXQoYW5nbGUsIHBpdGNoKTtcblxuICAgIHZhciBidWNrZXRzSW5PcmRlciA9IHRoaXMuYnVja2V0c0luT3JkZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYnVja2V0ID0gYnVja2V0c0luT3JkZXJbaV07XG5cbiAgICAgICAgaWYgKGJ1Y2tldC50eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgYnVja2V0LnBsYWNlRmVhdHVyZXMoYnVmZmVycywgY29sbGlzaW9uRGVidWcpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1tidWNrZXQuaWRdID0gYnVja2V0LmVsZW1lbnRHcm91cHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBrIGluIGJ1ZmZlcnMpIHtcbiAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGJ1ZmZlcnNba10uYXJyYXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHJlc3VsdDoge1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwczogZWxlbWVudEdyb3VwcyxcbiAgICAgICAgICAgIGJ1ZmZlcnM6IGJ1ZmZlcnNcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmZXJhYmxlczogdHJhbnNmZXJhYmxlc1xuICAgIH07XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQW5pbWF0aW9uTG9vcDtcblxuZnVuY3Rpb24gQW5pbWF0aW9uTG9vcCgpIHtcbiAgICB0aGlzLm4gPSAwO1xuICAgIHRoaXMudGltZXMgPSBbXTtcbn1cblxuLy8gQXJlIGFsbCBhbmltYXRpb25zIGRvbmU/XG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5zdG9wcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQudGltZSA+PSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgIH0pO1xuICAgIHJldHVybiAhdGhpcy50aW1lcy5sZW5ndGg7XG59O1xuXG4vLyBBZGQgYSBuZXcgYW5pbWF0aW9uIHRoYXQgd2lsbCBydW4gdCBtaWxsaXNlY29uZHNcbi8vIFJldHVybnMgYW4gaWQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgaXQgbGF5ZXJcbkFuaW1hdGlvbkxvb3AucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aGlzLnRpbWVzLnB1c2goeyBpZDogdGhpcy5uLCB0aW1lOiB0ICsgKG5ldyBEYXRlKCkpLmdldFRpbWUoKSB9KTtcbiAgICByZXR1cm4gdGhpcy5uKys7XG59O1xuXG4vLyBDYW5jZWwgYW4gYW5pbWF0aW9uXG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbihuKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQuaWQgIT09IG47XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSW1hZ2VTcHJpdGU7XG5cbmZ1bmN0aW9uIEltYWdlU3ByaXRlKGJhc2UpIHtcbiAgICB0aGlzLmJhc2UgPSBiYXNlO1xuICAgIHRoaXMucmV0aW5hID0gYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMTtcblxuICAgIGJhc2UgPSB0aGlzLmJhc2UgKyAodGhpcy5yZXRpbmEgPyAnQDJ4JyA6ICcnKTtcblxuICAgIGFqYXguZ2V0SlNPTihiYXNlICsgJy5qc29uJywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgaWYgKHRoaXMuaW1nKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgYWpheC5nZXRJbWFnZShiYXNlICsgJy5wbmcnLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByZW11bHRpcGx5IHRoZSBzcHJpdGVcbiAgICAgICAgdmFyIGRhdGEgPSBpbWcuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgbmV3ZGF0YSA9IGltZy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgICAgICAgIHZhciBhbHBoYSA9IGRhdGFbaSArIDNdIC8gMjU1O1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMF0gPSBkYXRhW2kgKyAwXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMV0gPSBkYXRhW2kgKyAxXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMl0gPSBkYXRhW2kgKyAyXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgM10gPSBkYXRhW2kgKyAzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW1nID0gaW1nO1xuICAgICAgICBpZiAodGhpcy5kYXRhKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5sb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gISEodGhpcy5kYXRhICYmIHRoaXMuaW1nKTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbigvKmdsKi8pIHtcbiAgICBpZiAoYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMSAhPT0gdGhpcy5yZXRpbmEpIHtcbiAgICAgICAgdmFyIG5ld1Nwcml0ZSA9IG5ldyBJbWFnZVNwcml0ZSh0aGlzLmJhc2UpO1xuICAgICAgICBuZXdTcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuaW1nID0gbmV3U3ByaXRlLmltZztcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ld1Nwcml0ZS5kYXRhO1xuICAgICAgICAgICAgdGhpcy5yZXRpbmEgPSBuZXdTcHJpdGUucmV0aW5hO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIFNwcml0ZVBvc2l0aW9uKCkge31cblNwcml0ZVBvc2l0aW9uLnByb3RvdHlwZSA9IHsgeDogMCwgeTogMCwgd2lkdGg6IDAsIGhlaWdodDogMCwgcGl4ZWxSYXRpbzogMSwgc2RmOiBmYWxzZSB9O1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUuZ2V0U3ByaXRlUG9zaXRpb24gPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCgpKSByZXR1cm4gbmV3IFNwcml0ZVBvc2l0aW9uKCk7XG5cbiAgICB2YXIgcG9zID0gdGhpcy5kYXRhICYmIHRoaXMuZGF0YVtuYW1lXTtcbiAgICBpZiAocG9zICYmIHRoaXMuaW1nKSByZXR1cm4gcG9zO1xuXG4gICAgcmV0dXJuIG5ldyBTcHJpdGVQb3NpdGlvbigpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge307XG5cbnJlZmVyZW5jZS5sYXlvdXQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BzKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIHRoaXNbcF0gPSBwcm9wc1twXTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHByb3AgaW4gcHJvcGVydGllcykge1xuICAgICAgICBpZiAocHJvcGVydGllc1twcm9wXS5kZWZhdWx0ID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBQcm9wZXJ0aWVzLnByb3RvdHlwZVtwcm9wXSA9IHByb3BlcnRpZXNbcHJvcF0uZGVmYXVsdDtcbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHNbY2xhc3NOYW1lLnJlcGxhY2UoJ2xheW91dF8nLCAnJyldID0gUHJvcGVydGllcztcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi9yZWZlcmVuY2UnKTtcbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5yZWZlcmVuY2UucGFpbnQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgQ2FsY3VsYXRlZCA9IGZ1bmN0aW9uKCkge307XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcykge1xuICAgICAgICB2YXIgcHJvcCA9IHByb3BlcnRpZXNbcF0sXG4gICAgICAgICAgICB2YWx1ZSA9IHByb3AuZGVmYXVsdDtcblxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgICAgIGlmIChwcm9wLnR5cGUgPT09ICdjb2xvcicpIHZhbHVlID0gcGFyc2VDU1NDb2xvcih2YWx1ZSk7XG5cbiAgICAgICAgQ2FsY3VsYXRlZC5wcm90b3R5cGVbcF0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBDYWxjdWxhdGVkLnByb3RvdHlwZS5oaWRkZW4gPSBmYWxzZTtcbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgncGFpbnRfJywgJycpXSA9IENhbGN1bGF0ZWQ7XG59KTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4uL3NvdXJjZS9zb3VyY2UnKTtcbnZhciBTdHlsZUxheWVyID0gcmVxdWlyZSgnLi9zdHlsZV9sYXllcicpO1xudmFyIEltYWdlU3ByaXRlID0gcmVxdWlyZSgnLi9pbWFnZV9zcHJpdGUnKTtcbnZhciBHbHlwaFNvdXJjZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nbHlwaF9zb3VyY2UnKTtcbnZhciBHbHlwaEF0bGFzID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoX2F0bGFzJyk7XG52YXIgU3ByaXRlQXRsYXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvc3ByaXRlX2F0bGFzJyk7XG52YXIgTGluZUF0bGFzID0gcmVxdWlyZSgnLi4vcmVuZGVyL2xpbmVfYXRsYXMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplU3R5bGVVUkw7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi91dGlsL2Rpc3BhdGNoZXInKTtcbnZhciBBbmltYXRpb25Mb29wID0gcmVxdWlyZSgnLi9hbmltYXRpb25fbG9vcCcpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvbGliL3ZhbGlkYXRlL2xhdGVzdCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlO1xuXG5mdW5jdGlvbiBTdHlsZShzdHlsZXNoZWV0LCBhbmltYXRpb25Mb29wKSB7XG4gICAgdGhpcy5hbmltYXRpb25Mb29wID0gYW5pbWF0aW9uTG9vcCB8fCBuZXcgQW5pbWF0aW9uTG9vcCgpO1xuICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKE1hdGgubWF4KGJyb3dzZXIuaGFyZHdhcmVDb25jdXJyZW5jeSAtIDEsIDEpLCB0aGlzKTtcbiAgICB0aGlzLmdseXBoQXRsYXMgPSBuZXcgR2x5cGhBdGxhcygxMDI0LCAxMDI0KTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzID0gbmV3IFNwcml0ZUF0bGFzKDUxMiwgNTEyKTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzLnJlc2l6ZShicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIHRoaXMubGluZUF0bGFzID0gbmV3IExpbmVBdGxhcygyNTYsIDUxMik7XG5cbiAgICB0aGlzLl9sYXllcnMgPSB7fTtcbiAgICB0aGlzLl9vcmRlciAgPSBbXTtcbiAgICB0aGlzLl9ncm91cHMgPSBbXTtcbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcblxuICAgIHRoaXMuem9vbUhpc3RvcnkgPSB7fTtcblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFNvdXJjZUV2ZW50JyxcbiAgICAgICAgJ19mb3J3YXJkVGlsZUV2ZW50JyxcbiAgICAgICAgJ19yZWRvUGxhY2VtZW50J1xuICAgIF0sIHRoaXMpO1xuXG4gICAgdmFyIGxvYWRlZCA9IGZ1bmN0aW9uKGVyciwgc3R5bGVzaGVldCkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKHN0eWxlc2hlZXQpO1xuICAgICAgICBpZiAodmFsaWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YWxpZC5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fbG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHlsZXNoZWV0ID0gc3R5bGVzaGVldDtcblxuICAgICAgICB2YXIgc291cmNlcyA9IHN0eWxlc2hlZXQuc291cmNlcztcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gc291cmNlcykge1xuICAgICAgICAgICAgdGhpcy5hZGRTb3VyY2UoaWQsIHNvdXJjZXNbaWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHlsZXNoZWV0LnNwcml0ZSkge1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUgPSBuZXcgSW1hZ2VTcHJpdGUoc3R5bGVzaGVldC5zcHJpdGUpO1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUub24oJ2xvYWQnLCB0aGlzLmZpcmUuYmluZCh0aGlzLCAnY2hhbmdlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZSA9IG5ldyBHbHlwaFNvdXJjZShzdHlsZXNoZWV0LmdseXBocywgdGhpcy5nbHlwaEF0bGFzKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBpZiAodHlwZW9mIHN0eWxlc2hlZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTihub3JtYWxpemVVUkwoc3R5bGVzaGVldCksIGxvYWRlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnJvd3Nlci5mcmFtZShsb2FkZWQuYmluZCh0aGlzLCBudWxsLCBzdHlsZXNoZWV0KSk7XG4gICAgfVxufVxuXG5TdHlsZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKVxuICAgICAgICAgICAgaWYgKCF0aGlzLnNvdXJjZXNbaWRdLmxvYWRlZCgpKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAodGhpcy5zcHJpdGUgJiYgIXRoaXMuc3ByaXRlLmxvYWRlZCgpKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBfcmVzb2x2ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBpZCwgbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5fbGF5ZXJzID0ge307XG4gICAgICAgIHRoaXMuX29yZGVyICA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zdHlsZXNoZWV0LmxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGF5ZXIgPSBuZXcgU3R5bGVMYXllcih0aGlzLnN0eWxlc2hlZXQubGF5ZXJzW2ldLCB0aGlzLnN0eWxlc2hlZXQuY29uc3RhbnRzIHx8IHt9KTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgICAgIHRoaXMuX29yZGVyLnB1c2gobGF5ZXIuaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsYXlvdXQgcHJvcGVydGllcy5cbiAgICAgICAgZm9yIChpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZUxheW91dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSByZWZlcmVuY2UgYW5kIHBhaW50IHByb3BlcnRpZXMuXG4gICAgICAgIGZvciAoaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLnJlc29sdmVSZWZlcmVuY2UodGhpcy5fbGF5ZXJzKTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZVBhaW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICB9LFxuXG4gICAgX2dyb3VwTGF5ZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdyb3VwO1xuXG4gICAgICAgIHRoaXMuX2dyb3VwcyA9IFtdO1xuXG4gICAgICAgIC8vIFNwbGl0IGludG8gZ3JvdXBzIG9mIGNvbnNlY3V0aXZlIHRvcC1sZXZlbCBsYXllcnMgd2l0aCB0aGUgc2FtZSBzb3VyY2UuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fb3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1t0aGlzLl9vcmRlcltpXV07XG5cbiAgICAgICAgICAgIGlmICghZ3JvdXAgfHwgbGF5ZXIuc291cmNlICE9PSBncm91cC5zb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwLnNvdXJjZSA9IGxheWVyLnNvdXJjZTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ncm91cHMucHVzaChncm91cCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdyb3VwLnB1c2gobGF5ZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9icm9hZGNhc3RMYXllcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb3JkZXJlZCA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgb3JkZXJlZC5wdXNoKHRoaXMuX2xheWVyc1tpZF0uanNvbigpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoJ3NldCBsYXllcnMnLCBvcmRlcmVkKTtcbiAgICB9LFxuXG4gICAgX2Nhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpIHJldHVybjtcblxuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLmNhc2NhZGUoY2xhc3Nlcywgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICB0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbiB8fCB7fSxcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICB9LFxuXG4gICAgX3JlY2FsY3VsYXRlOiBmdW5jdGlvbih6KSB7XG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuc291cmNlcylcbiAgICAgICAgICAgIHRoaXMuc291cmNlc1tpZF0udXNlZCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZVpvb21IaXN0b3J5KHopO1xuXG4gICAgICAgIHRoaXMucmFzdGVyRmFkZUR1cmF0aW9uID0gMzAwO1xuICAgICAgICBmb3IgKGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgdmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcblxuICAgICAgICAgICAgaWYgKGxheWVyLnJlY2FsY3VsYXRlKHosIHRoaXMuem9vbUhpc3RvcnkpICYmIGxheWVyLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1heFpvb21UcmFuc2l0aW9uRHVyYXRpb24gPSAzMDA7XG4gICAgICAgIGlmIChNYXRoLmZsb29yKHRoaXMueikgIT09IE1hdGguZmxvb3IoeikpIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uTG9vcC5zZXQobWF4Wm9vbVRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnogPSB6O1xuICAgICAgICB0aGlzLmZpcmUoJ3pvb20nKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVpvb21IaXN0b3J5OiBmdW5jdGlvbih6KSB7XG5cbiAgICAgICAgdmFyIHpoID0gdGhpcy56b29tSGlzdG9yeTtcblxuICAgICAgICBpZiAoemgubGFzdEludGVnZXJab29tID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGZpcnN0IHRpbWVcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbSA9IE1hdGguZmxvb3Ioeik7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb21UaW1lID0gMDtcbiAgICAgICAgICAgIHpoLmxhc3Rab29tID0gejtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgYW4gaW50ZWdlciB6b29tIGxldmVsIGFzIHBhc3NlZCBzaW5jZSB0aGUgbGFzdCBmcmFtZVxuICAgICAgICAvLyBhbmQgaWYgeWVzLCByZWNvcmQgaXQgd2l0aCB0aGUgdGltZS4gVXNlZCBmb3IgdHJhbnNpdGlvbmluZyBwYXR0ZXJucy5cbiAgICAgICAgaWYgKE1hdGguZmxvb3IoemgubGFzdFpvb20pIDwgTWF0aC5mbG9vcih6KSkge1xuICAgICAgICAgICAgemgubGFzdEludGVnZXJab29tID0gTWF0aC5mbG9vcih6KTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoTWF0aC5mbG9vcih6aC5sYXN0Wm9vbSkgPiBNYXRoLmZsb29yKHopKSB7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb20gPSBNYXRoLmZsb29yKHogKyAxKTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgemgubGFzdFpvb20gPSB6O1xuICAgIH0sXG5cbiAgICBhZGRTb3VyY2U6IGZ1bmN0aW9uKGlkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMuc291cmNlc1tpZF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBpcyBhbHJlYWR5IGEgc291cmNlIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIHNvdXJjZSA9IFNvdXJjZS5jcmVhdGUoc291cmNlKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2lkXSA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlLmlkID0gaWQ7XG4gICAgICAgIHNvdXJjZS5zdHlsZSA9IHRoaXM7XG4gICAgICAgIHNvdXJjZS5kaXNwYXRjaGVyID0gdGhpcy5kaXNwYXRjaGVyO1xuICAgICAgICBzb3VyY2UuZ2x5cGhBdGxhcyA9IHRoaXMuZ2x5cGhBdGxhcztcbiAgICAgICAgc291cmNlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCdjaGFuZ2UnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUucmVtb3ZlJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudCk7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLmFkZCcsIHtzb3VyY2U6IHNvdXJjZX0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgc291cmNlIGZyb20gdGhpcyBzdHlsZXNoZWV0LCBnaXZlbiBpdHMgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBzb3VyY2UgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMge1N0eWxlfSB0aGlzIHN0eWxlXG4gICAgICogQHRocm93cyB7RXJyb3J9IGlmIG5vIHNvdXJjZSBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlU291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHNvdXJjZSB3aXRoIHRoaXMgSUQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgIHNvdXJjZVxuICAgICAgICAgICAgLm9mZignbG9hZCcsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZignY2hhbmdlJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5hZGQnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ3RpbGUuZXJyb3InLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KTtcbiAgICAgICAgdGhpcy5maXJlKCdzb3VyY2UucmVtb3ZlJywge3NvdXJjZTogc291cmNlfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzb3VyY2UgYnkgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBkZXNpcmVkIHNvdXJjZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHNvdXJjZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0U291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgbGF5ZXIgdG8gdGhlIG1hcCBzdHlsZS4gVGhlIGxheWVyIHdpbGwgYmUgaW5zZXJ0ZWQgYmVmb3JlIHRoZSBsYXllciB3aXRoXG4gICAgICogSUQgYGJlZm9yZWAsIG9yIGFwcGVuZGVkIGlmIGBiZWZvcmVgIGlzIG9taXR0ZWQuXG4gICAgICogQHBhcmFtIHtTdHlsZUxheWVyfE9iamVjdH0gbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGJlZm9yZSAgSUQgb2YgYW4gZXhpc3RpbmcgbGF5ZXIgdG8gaW5zZXJ0IGJlZm9yZVxuICAgICAqIEBmaXJlcyBsYXllci5hZGRcbiAgICAgKiBAcmV0dXJucyB7U3R5bGV9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZExheWVyOiBmdW5jdGlvbihsYXllciwgYmVmb3JlKSB7XG4gICAgICAgIGlmICh0aGlzLl9sYXllcnNbbGF5ZXIuaWRdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgYWxyZWFkeSBhIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKGxheWVyIGluc3RhbmNlb2YgU3R5bGVMYXllcikpIHtcbiAgICAgICAgICAgIGxheWVyID0gbmV3IFN0eWxlTGF5ZXIobGF5ZXIsIHRoaXMuc3R5bGVzaGVldC5jb25zdGFudHMgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgdGhpcy5fb3JkZXIuc3BsaWNlKGJlZm9yZSA/IHRoaXMuX29yZGVyLmluZGV4T2YoYmVmb3JlKSA6IEluZmluaXR5LCAwLCBsYXllci5pZCk7XG4gICAgICAgIGxheWVyLnJlc29sdmVMYXlvdXQoKTtcbiAgICAgICAgbGF5ZXIucmVzb2x2ZVJlZmVyZW5jZSh0aGlzLl9sYXllcnMpO1xuICAgICAgICBsYXllci5yZXNvbHZlUGFpbnQoKTtcbiAgICAgICAgdGhpcy5fZ3JvdXBMYXllcnMoKTtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuZmlyZSgnbGF5ZXIuYWRkJywge2xheWVyOiBsYXllcn0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgbGF5ZXIgZnJvbSB0aGlzIHN0eWxlc2hlZXQsIGdpdmVuIGl0cyBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGxheWVyIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtTdHlsZX0gdGhpcyBzdHlsZVxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBsYXllciBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XG4gICAgICAgIGlmIChsYXllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fbGF5ZXJzW2ldLnJlZiA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxheWVyKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xuICAgICAgICB0aGlzLl9vcmRlci5zcGxpY2UodGhpcy5fb3JkZXIuaW5kZXhPZihpZCksIDEpO1xuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5maXJlKCdsYXllci5yZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllciBieSBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGRlc2lyZWQgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyB7TGF5ZXJ9IGxheWVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXllcjogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xheWVyc1tpZF07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIElmIGEgbGF5ZXIgaGFzIGEgYHJlZmAgcHJvcGVydHkgdGhhdCBtYWtlcyBpdCBkZXJpdmUgc29tZSB2YWx1ZXNcbiAgICAgKiBmcm9tIGFub3RoZXIgbGF5ZXIsIHJldHVybiB0aGF0IHJlZmVyZW50IGxheWVyLiBPdGhlcndpc2UsXG4gICAgICogcmV0dXJucyB0aGUgbGF5ZXIgaXRzZWxmLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZCB0aGUgbGF5ZXIncyBpZFxuICAgICAqIEByZXR1cm5zIHtMYXllcn0gdGhlIHJlZmVyZW50IGxheWVyIG9yIHRoZSBsYXllciBpdHNlbGZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldFJlZmVyZW50TGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoaWQpO1xuICAgICAgICBpZiAobGF5ZXIucmVmKSB7XG4gICAgICAgICAgICBsYXllciA9IHRoaXMuZ2V0TGF5ZXIobGF5ZXIucmVmKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfSxcblxuICAgIHNldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIsIGZpbHRlcikge1xuICAgICAgICBsYXllciA9IHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcik7XG4gICAgICAgIGxheWVyLmZpbHRlciA9IGZpbHRlcjtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnJlbG9hZCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllcidzIGZpbHRlciBvYmplY3RcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbGF5ZXIgdGhlIGxheWVyIHRvIGluc3BlY3RcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIGxheWVyJ3MgZmlsdGVyLCBpZiBhbnlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZmlsdGVyO1xuICAgIH0sXG5cbiAgICBzZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIGxheWVyID0gdGhpcy5nZXRSZWZlcmVudExheWVyKGxheWVyKTtcbiAgICAgICAgbGF5ZXIuc2V0TGF5b3V0UHJvcGVydHkobmFtZSwgdmFsdWUpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2xheWVyLnNvdXJjZV0ucmVsb2FkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhIGxheW91dCBwcm9wZXJ0eSdzIHZhbHVlIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBsYXllciB0aGUgbGF5ZXIgdG8gaW5zcGVjdFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIHByb3BlcnR5IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZ2V0TGF5b3V0UHJvcGVydHkobmFtZSk7XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSwga2xhc3MpIHtcbiAgICAgICAgdGhpcy5nZXRMYXllcihsYXllcikuc2V0UGFpbnRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihsYXllciwgbmFtZSwga2xhc3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGF5ZXIobGF5ZXIpLmdldFBhaW50UHJvcGVydHkobmFtZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihjb29yZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICAgICAgdmFyIGVycm9yID0gbnVsbDtcblxuICAgICAgICBpZiAocGFyYW1zLmxheWVyKSB7XG4gICAgICAgICAgICBwYXJhbXMubGF5ZXIgPSB7IGlkOiBwYXJhbXMubGF5ZXIgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHV0aWwuYXN5bmNFYWNoKE9iamVjdC5rZXlzKHRoaXMuc291cmNlcyksIGZ1bmN0aW9uKGlkLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgICAgICBzb3VyY2UuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBmdW5jdGlvbihlcnIsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIGZlYXR1cmVzID0gZmVhdHVyZXMuY29uY2F0KHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycikgZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LmJpbmQodGhpcyksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuXG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBmZWF0dXJlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmxheWVyID0gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZlYXR1cmU7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXIucmVtb3ZlKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVTb3VyY2VzOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZXNbaWRdLnVwZGF0ZSh0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9yZWRvUGxhY2VtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXS5yZWRvUGxhY2VtZW50KSB0aGlzLnNvdXJjZXNbaWRdLnJlZG9QbGFjZW1lbnQoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfZm9yd2FyZFNvdXJjZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzb3VyY2U6IGUudGFyZ2V0fSwgZSkpO1xuICAgIH0sXG5cbiAgICBfZm9yd2FyZFRpbGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoZS50eXBlLCB1dGlsLmV4dGVuZCh7c291cmNlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgLy8gQ2FsbGJhY2tzIGZyb20gd2ViIHdvcmtlcnNcblxuICAgICdnZXQgc3ByaXRlIGpzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgeyBzcHJpdGU6IHNwcml0ZS5kYXRhLCByZXRpbmE6IHNwcml0ZS5yZXRpbmEgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7IHNwcml0ZTogc3ByaXRlLmRhdGEsIHJldGluYTogc3ByaXRlLnJldGluYSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgICdnZXQgaWNvbnMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgdmFyIHNwcml0ZUF0bGFzID0gdGhpcy5zcHJpdGVBdGxhcztcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHNwcml0ZSk7XG4gICAgICAgICAgICBzcHJpdGVBdGxhcy5hZGRJY29ucyhwYXJhbXMuaWNvbnMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwcml0ZS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLnNldFNwcml0ZShzcHJpdGUpO1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLmFkZEljb25zKHBhcmFtcy5pY29ucywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2dldCBnbHlwaHMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2x5cGhTb3VyY2UuZ2V0U2ltcGxlR2x5cGhzKHBhcmFtcy5mb250c3RhY2ssIHBhcmFtcy5jb2RlcG9pbnRzLCBwYXJhbXMudWlkLCBjYWxsYmFjayk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmV4cG9ydHMucmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb25zdGFudHMpIHtcbiAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlWzBdID09PSAnQCcgPyBjb25zdGFudHNbdmFsdWVdIDogdmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIGk7XG5cbiAgICB2YWx1ZSA9IHJlc29sdmUodmFsdWUpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtpXSBpbiBjb25zdGFudHMpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtpXSA9IHJlc29sdmUodmFsdWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHZhbHVlID0gdXRpbC5leHRlbmQoe30sIHZhbHVlKTtcbiAgICAgICAgdmFsdWUuc3RvcHMgPSB2YWx1ZS5zdG9wcy5zbGljZSgpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5zdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHZhbHVlLnN0b3BzW2ldWzFdIGluIGNvbnN0YW50cykge1xuICAgICAgICAgICAgICAgIHZhbHVlLnN0b3BzW2ldID0gW1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXVswXSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS5zdG9wc1tpXVsxXSlcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0cy5yZXNvbHZlQWxsID0gZnVuY3Rpb24gKHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIGlmICghY29uc3RhbnRzKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcblxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIGZvciAodmFyIGtleSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gZXhwb3J0cy5yZXNvbHZlKHByb3BlcnRpZXNba2V5XSwgY29uc3RhbnRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhcnNlQ1NTQ29sb3IgPSByZXF1aXJlKCdjc3Njb2xvcnBhcnNlcicpLnBhcnNlQ1NTQ29sb3I7XG52YXIgbWFwYm94R0xGdW5jdGlvbiA9IHJlcXVpcmUoJ21hcGJveC1nbC1mdW5jdGlvbicpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZURlY2xhcmF0aW9uO1xuXG5mdW5jdGlvbiBTdHlsZURlY2xhcmF0aW9uKHJlZmVyZW5jZSwgdmFsdWUpIHtcbiAgICB0aGlzLnR5cGUgPSByZWZlcmVuY2UudHlwZTtcbiAgICB0aGlzLnRyYW5zaXRpb25hYmxlID0gcmVmZXJlbmNlLnRyYW5zaXRpb247XG5cbiAgICAvLyBpbW11dGFibGUgcmVwcmVzZW50YXRpb24gb2YgdmFsdWUuIHVzZWQgZm9yIGNvbXBhcmlzb25cbiAgICB0aGlzLmpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbiAgICBpZiAodGhpcy50eXBlICE9PSAnY29sb3InKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBwcmVwYXJlQ29sb3JGdW5jdGlvbih2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHBhcnNlQ29sb3IodmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChyZWZlcmVuY2UuZnVuY3Rpb24gPT09ICdpbnRlcnBvbGF0ZWQnKSB7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlID0gbWFwYm94R0xGdW5jdGlvbi5pbnRlcnBvbGF0ZWQodGhpcy52YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jYWxjdWxhdGUgPSBtYXBib3hHTEZ1bmN0aW9uWydwaWVjZXdpc2UtY29uc3RhbnQnXSh0aGlzLnZhbHVlKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZS50cmFuc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZSA9IHRyYW5zaXRpb25lZCh0aGlzLmNhbGN1bGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb25lZChjYWxjdWxhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeiwgemgsIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBmcmFjdGlvbiA9IHogJSAxO1xuICAgICAgICB2YXIgdCA9IE1hdGgubWluKChEYXRlLm5vdygpIC0gemgubGFzdEludGVnZXJab29tVGltZSkgLyBkdXJhdGlvbiwgMSk7XG4gICAgICAgIHZhciBmcm9tU2NhbGUgPSAxO1xuICAgICAgICB2YXIgdG9TY2FsZSA9IDE7XG4gICAgICAgIHZhciBtaXgsIGZyb20sIHRvO1xuXG4gICAgICAgIGlmICh6ID4gemgubGFzdEludGVnZXJab29tKSB7XG4gICAgICAgICAgICBtaXggPSBmcmFjdGlvbiArICgxIC0gZnJhY3Rpb24pICogdDtcbiAgICAgICAgICAgIGZyb21TY2FsZSAqPSAyO1xuICAgICAgICAgICAgZnJvbSA9IGNhbGN1bGF0ZSh6IC0gMSk7XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1peCA9IDEgLSAoMSAtIHQpICogZnJhY3Rpb247XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgICAgIGZyb20gPSBjYWxjdWxhdGUoeiArIDEpO1xuICAgICAgICAgICAgZnJvbVNjYWxlIC89IDI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgIGZyb21TY2FsZTogZnJvbVNjYWxlLFxuICAgICAgICAgICAgdG86IHRvLFxuICAgICAgICAgICAgdG9TY2FsZTogdG9TY2FsZSxcbiAgICAgICAgICAgIHQ6IG1peFxuICAgICAgICB9O1xuICAgIH07XG59XG5cbnZhciBjb2xvckNhY2hlID0ge307XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3IodmFsdWUpIHtcbiAgICBpZiAoY29sb3JDYWNoZVt2YWx1ZV0pIHJldHVybiBjb2xvckNhY2hlW3ZhbHVlXTtcbiAgICB2YXIgY29sb3IgPSBwcmVwYXJlQ29sb3IocGFyc2VDU1NDb2xvcih2YWx1ZSkpO1xuICAgIGNvbG9yQ2FjaGVbdmFsdWVdID0gY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3IoYykge1xuICAgIHJldHVybiBbY1swXSAvIDI1NSwgY1sxXSAvIDI1NSwgY1syXSAvIDI1NSwgY1szXSAvIDFdO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3JGdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIHV0aWwuZXh0ZW5kKHt9LCBmLCB7c3RvcHM6IGYuc3RvcHMubWFwKGZ1bmN0aW9uKHN0b3ApIHtcbiAgICAgICAgcmV0dXJuIFtzdG9wWzBdLCBwYXJzZUNvbG9yKHN0b3BbMV0pXTtcbiAgICB9KX0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbicpO1xuXG52YXIgbG9va3VwID0ge1xuICAgIHBhaW50OiB7fSxcbiAgICBsYXlvdXQ6IHt9XG59O1xuXG5yZWZlcmVuY2UubGF5ZXIudHlwZS52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih0eXBlKSB7XG4gICAgbG9va3VwLnBhaW50W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsncGFpbnRfJyArIHR5cGVdKTtcbiAgICBsb29rdXAubGF5b3V0W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsnbGF5b3V0XycgKyB0eXBlXSk7XG59KTtcblxuZnVuY3Rpb24gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZSkge1xuICAgIGZ1bmN0aW9uIFN0eWxlRGVjbGFyYXRpb25TZXQocHJvcGVydGllcywgY29uc3RhbnRzKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IHt9O1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9ucyA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2NvbnN0YW50cyA9IGNvbnN0YW50cztcblxuICAgICAgICBmb3IgKHZhciBrIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXNba10gPSBTdHlsZUNvbnN0YW50LnJlc29sdmUocHJvcGVydGllc1trXSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKHJlZmVyZW5jZSkuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgICAgIHZhciBwcm9wZXJ0eSA9IHJlZmVyZW5jZVtrXTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3R5bGVEZWNsYXJhdGlvblNldC5wcm90b3R5cGUsIGssIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlc1trXSA9IG5ldyBTdHlsZURlY2xhcmF0aW9uKHByb3BlcnR5LCBTdHlsZUNvbnN0YW50LnJlc29sdmUodiwgdGhpcy5fY29uc3RhbnRzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzW2tdLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocHJvcGVydHkudHJhbnNpdGlvbikge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLCBrICsgJy10cmFuc2l0aW9uJywge1xuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2l0aW9uc1trXSA9IHY7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNpdGlvbnNba107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xuICAgIH07XG5cbiAgICBTdHlsZURlY2xhcmF0aW9uU2V0LnByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24oaywgZ2xvYmFsKSB7XG4gICAgICAgIHZhciB0ID0gdGhpcy5fdHJhbnNpdGlvbnNba10gfHwge307XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogdXRpbC5jb2FsZXNjZSh0LmR1cmF0aW9uLCBnbG9iYWwuZHVyYXRpb24sIDMwMCksXG4gICAgICAgICAgICBkZWxheTogdXRpbC5jb2FsZXNjZSh0LmRlbGF5LCBnbG9iYWwuZGVsYXksIDApXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgIGZvciAodmFyIHYgaW4gdGhpcy5fdmFsdWVzKSB7XG4gICAgICAgICAgICByZXN1bHRbdl0gPSB0aGlzLl92YWx1ZXNbdl0udmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMuX3RyYW5zaXRpb25zKSB7XG4gICAgICAgICAgICByZXN1bHRbdCArICctdHJhbnNpdGlvbiddID0gdGhpcy5fdHJhbnNpdGlvbnNbdl07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICByZXR1cm4gU3R5bGVEZWNsYXJhdGlvblNldDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihyZW5kZXJUeXBlLCBsYXllclR5cGUsIHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIHJldHVybiBuZXcgbG9va3VwW3JlbmRlclR5cGVdW2xheWVyVHlwZV0ocHJvcGVydGllcywgY29uc3RhbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZVRyYW5zaXRpb24gPSByZXF1aXJlKCcuL3N0eWxlX3RyYW5zaXRpb24nKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uU2V0ID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbl9zZXQnKTtcbnZhciBMYXlvdXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9sYXlvdXRfcHJvcGVydGllcycpO1xudmFyIFBhaW50UHJvcGVydGllcyA9IHJlcXVpcmUoJy4vcGFpbnRfcHJvcGVydGllcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFN0eWxlTGF5ZXIobGF5ZXIsIGNvbnN0YW50cykge1xuICAgIHRoaXMuX2xheWVyID0gbGF5ZXI7XG4gICAgdGhpcy5fY29uc3RhbnRzID0gY29uc3RhbnRzO1xuXG4gICAgdGhpcy5pZCA9IGxheWVyLmlkO1xuICAgIHRoaXMucmVmID0gbGF5ZXIucmVmO1xuXG4gICAgLy8gUmVzb2x2ZWQgYW5kIGNhc2NhZGVkIHBhaW50IHByb3BlcnRpZXMuXG4gICAgdGhpcy5fcmVzb2x2ZWQgPSB7fTsgLy8gY2xhc3MgbmFtZSAtPiBTdHlsZURlY2xhcmF0aW9uU2V0XG4gICAgdGhpcy5fY2FzY2FkZWQgPSB7fTsgLy8gcHJvcGVydHkgbmFtZSAtPiBTdHlsZVRyYW5zaXRpb25cblxuICAgIHRoaXMuYXNzaWduKGxheWVyKTtcbn1cblxuU3R5bGVMYXllci5wcm90b3R5cGUgPSB7XG4gICAgcmVzb2x2ZUxheW91dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5yZWYpIHtcbiAgICAgICAgICAgIHRoaXMubGF5b3V0ID0gbmV3IExheW91dFByb3BlcnRpZXNbdGhpcy50eXBlXShcbiAgICAgICAgICAgICAgICBTdHlsZUNvbnN0YW50LnJlc29sdmVBbGwodGhpcy5fbGF5ZXIubGF5b3V0LCB0aGlzLl9jb25zdGFudHMpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMubGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5sYXlvdXQuaGFzT3duUHJvcGVydHkoJ3RleHQtcm90YXRpb24tYWxpZ25tZW50JykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPSAnbWFwJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxheW91dC5oYXNPd25Qcm9wZXJ0eSgnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnc3ltYm9sLWF2b2lkLWVkZ2VzJ10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldExheW91dFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmxheW91dFtuYW1lXSA9IFN0eWxlQ29uc3RhbnQucmVzb2x2ZSh2YWx1ZSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICB9LFxuXG4gICAgZ2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGF5b3V0W25hbWVdO1xuICAgIH0sXG5cbiAgICByZXNvbHZlUmVmZXJlbmNlOiBmdW5jdGlvbihsYXllcnMpIHtcbiAgICAgICAgaWYgKHRoaXMucmVmKSB7XG4gICAgICAgICAgICB0aGlzLmFzc2lnbihsYXllcnNbdGhpcy5yZWZdKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZXNvbHZlUGFpbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBwIGluIHRoaXMuX2xheWVyKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBwLm1hdGNoKC9ecGFpbnQoPzpcXC4oLiopKT8kLyk7XG4gICAgICAgICAgICBpZiAoIW1hdGNoKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZWRbbWF0Y2hbMV0gfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHRoaXMuX2xheWVyW3BdLCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucykge1xuICAgICAgICAgICAgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHt9LCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgICAgIGRlY2xhcmF0aW9uc1tuYW1lXSA9IHZhbHVlO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucylcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBkZWNsYXJhdGlvbnNbbmFtZV07XG4gICAgfSxcblxuICAgIGNhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMsIGdsb2JhbFRyYW5zLCBhbmltYXRpb25Mb29wKSB7XG4gICAgICAgIGZvciAodmFyIGtsYXNzIGluIHRoaXMuX3Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpZiAoa2xhc3MgIT09IFwiXCIgJiYgIWNsYXNzZXNba2xhc3NdKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3NdLFxuICAgICAgICAgICAgICAgIHZhbHVlcyA9IGRlY2xhcmF0aW9ucy52YWx1ZXMoKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgayBpbiB2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RGVjbGFyYXRpb24gPSB2YWx1ZXNba107XG4gICAgICAgICAgICAgICAgdmFyIG9sZFRyYW5zaXRpb24gPSBvcHRpb25zLnRyYW5zaXRpb24gPyB0aGlzLl9jYXNjYWRlZFtrXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IHRyYW5zaXRpb24gaWYgdGhlIGRlY2xhcmF0aW9uIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpZiAoIW9sZFRyYW5zaXRpb24gfHwgb2xkVHJhbnNpdGlvbi5kZWNsYXJhdGlvbi5qc29uICE9PSBuZXdEZWNsYXJhdGlvbi5qc29uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdTdHlsZVRyYW5zID0gZGVjbGFyYXRpb25zLnRyYW5zaXRpb24oaywgZ2xvYmFsVHJhbnMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMuX2Nhc2NhZGVkW2tdID1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTdHlsZVRyYW5zaXRpb24obmV3RGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIG5ld1N0eWxlVHJhbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJ1biB0aGUgYW5pbWF0aW9uIGxvb3AgdW50aWwgdGhlIGVuZCBvZiB0aGUgdHJhbnNpdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld1RyYW5zaXRpb24uaW5zdGFudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdUcmFuc2l0aW9uLmxvb3BJRCA9IGFuaW1hdGlvbkxvb3Auc2V0KG5ld1RyYW5zaXRpb24uZW5kVGltZSAtIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkxvb3AuY2FuY2VsKG9sZFRyYW5zaXRpb24ubG9vcElEKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZWNhbGN1bGF0ZTogZnVuY3Rpb24oeiwgem9vbUhpc3RvcnkpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLnR5cGUsXG4gICAgICAgICAgICBjYWxjdWxhdGVkID0gdGhpcy5wYWludCA9IG5ldyBQYWludFByb3BlcnRpZXNbdHlwZV0oKTtcblxuICAgICAgICBmb3IgKHZhciBrIGluIHRoaXMuX2Nhc2NhZGVkKSB7XG4gICAgICAgICAgICBjYWxjdWxhdGVkW2tdID0gdGhpcy5fY2FzY2FkZWRba10uYXQoeiwgem9vbUhpc3RvcnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRkZW4gPSAodGhpcy5taW56b29tICYmIHogPCB0aGlzLm1pbnpvb20pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHRoaXMubWF4em9vbSAmJiB6ID49IHRoaXMubWF4em9vbSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpbmNsdWRlIHZpc2liaWxpdHkgY2hlY2sgZm9yIG5vbi1idWNrZXRlZCBiYWNrZ3JvdW5kIGxheWVyc1xuICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmxheW91dC52aXNpYmlsaXR5ID09PSAnbm9uZScpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgaWYgKChjYWxjdWxhdGVkWyd0ZXh0LW9wYWNpdHknXSA9PT0gMCB8fCAhdGhpcy5sYXlvdXRbJ3RleHQtZmllbGQnXSkgJiZcbiAgICAgICAgICAgICAgICAoY2FsY3VsYXRlZFsnaWNvbi1vcGFjaXR5J10gPT09IDAgfHwgIXRoaXMubGF5b3V0WydpY29uLWltYWdlJ10pKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVtdWx0aXBseUxheWVyKGNhbGN1bGF0ZWQsICd0ZXh0Jyk7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihjYWxjdWxhdGVkLCAnaWNvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY2FsY3VsYXRlZFt0eXBlICsgJy1vcGFjaXR5J10gPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZW11bHRpcGx5TGF5ZXIoY2FsY3VsYXRlZCwgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY2FzY2FkZWRbJ2xpbmUtZGFzaGFycmF5J10pIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBsaW5lIGlzIGRhc2hlZCwgc2NhbGUgdGhlIGRhc2ggbGVuZ3RocyBieSB0aGUgbGluZVxuICAgICAgICAgICAgLy8gd2lkdGggYXQgdGhlIHByZXZpb3VzIHJvdW5kIHpvb20gbGV2ZWwuXG4gICAgICAgICAgICB2YXIgZGFzaEFycmF5ID0gY2FsY3VsYXRlZFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICAgICAgICAgIHZhciBsaW5lV2lkdGggPSB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddID9cbiAgICAgICAgICAgICAgICB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddLmF0KE1hdGguZmxvb3IoeiksIEluZmluaXR5KSA6XG4gICAgICAgICAgICAgICAgY2FsY3VsYXRlZFsnbGluZS13aWR0aCddO1xuXG4gICAgICAgICAgICBkYXNoQXJyYXkuZnJvbVNjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgICAgIGRhc2hBcnJheS50b1NjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfSxcblxuICAgIGFzc2lnbjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKGxheWVyLFxuICAgICAgICAgICAgWyd0eXBlJywgJ3NvdXJjZScsICdzb3VyY2UtbGF5ZXInLFxuICAgICAgICAgICAgJ21pbnpvb20nLCAnbWF4em9vbScsICdmaWx0ZXInLFxuICAgICAgICAgICAgJ2xheW91dCddKSk7XG4gICAgfSxcblxuICAgIGpzb246IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdXRpbC5leHRlbmQoe30sXG4gICAgICAgICAgICB0aGlzLl9sYXllcixcbiAgICAgICAgICAgIHV0aWwucGljayh0aGlzLFxuICAgICAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJyxcbiAgICAgICAgICAgICAgICAnbWluem9vbScsICdtYXh6b29tJywgJ2ZpbHRlcicsXG4gICAgICAgICAgICAgICAgJ2xheW91dCcsICdwYWludCddKSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcHJlbXVsdGlwbHlMYXllcihsYXllciwgdHlwZSkge1xuICAgIHZhciBjb2xvclByb3AgPSB0eXBlICsgJy1jb2xvcicsXG4gICAgICAgIGhhbG9Qcm9wID0gdHlwZSArICctaGFsby1jb2xvcicsXG4gICAgICAgIG91dGxpbmVQcm9wID0gdHlwZSArICctb3V0bGluZS1jb2xvcicsXG4gICAgICAgIGNvbG9yID0gbGF5ZXJbY29sb3JQcm9wXSxcbiAgICAgICAgaGFsb0NvbG9yID0gbGF5ZXJbaGFsb1Byb3BdLFxuICAgICAgICBvdXRsaW5lQ29sb3IgPSBsYXllcltvdXRsaW5lUHJvcF0sXG4gICAgICAgIG9wYWNpdHkgPSBsYXllclt0eXBlICsgJy1vcGFjaXR5J107XG5cbiAgICB2YXIgY29sb3JPcGFjaXR5ID0gY29sb3IgJiYgKG9wYWNpdHkgKiBjb2xvclszXSk7XG4gICAgdmFyIGhhbG9PcGFjaXR5ID0gaGFsb0NvbG9yICYmIChvcGFjaXR5ICogaGFsb0NvbG9yWzNdKTtcbiAgICB2YXIgb3V0bGluZU9wYWNpdHkgPSBvdXRsaW5lQ29sb3IgJiYgKG9wYWNpdHkgKiBvdXRsaW5lQ29sb3JbM10pO1xuXG4gICAgaWYgKGNvbG9yT3BhY2l0eSAhPT0gdW5kZWZpbmVkICYmIGNvbG9yT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbY29sb3JQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW2NvbG9yWzBdLCBjb2xvclsxXSwgY29sb3JbMl0sIGNvbG9yT3BhY2l0eV0pO1xuICAgIH1cbiAgICBpZiAoaGFsb09wYWNpdHkgIT09IHVuZGVmaW5lZCAmJiBoYWxvT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbaGFsb1Byb3BdID0gdXRpbC5wcmVtdWx0aXBseShbaGFsb0NvbG9yWzBdLCBoYWxvQ29sb3JbMV0sIGhhbG9Db2xvclsyXSwgaGFsb09wYWNpdHldKTtcbiAgICB9XG4gICAgaWYgKG91dGxpbmVPcGFjaXR5ICE9PSB1bmRlZmluZWQgJiYgb3V0bGluZU9wYWNpdHkgPCAxKSB7XG4gICAgICAgIGxheWVyW291dGxpbmVQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW291dGxpbmVDb2xvclswXSwgb3V0bGluZUNvbG9yWzFdLCBvdXRsaW5lQ29sb3JbMl0sIG91dGxpbmVPcGFjaXR5XSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlVHJhbnNpdGlvbjtcblxuLypcbiAqIFJlcHJlc2VudHMgYSB0cmFuc2l0aW9uIGJldHdlZW4gdHdvIGRlY2xhcmF0aW9uc1xuICovXG5mdW5jdGlvbiBTdHlsZVRyYW5zaXRpb24oZGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIHZhbHVlKSB7XG5cbiAgICB0aGlzLmRlY2xhcmF0aW9uID0gZGVjbGFyYXRpb247XG4gICAgdGhpcy5zdGFydFRpbWUgPSB0aGlzLmVuZFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgdmFyIHR5cGUgPSBkZWNsYXJhdGlvbi50eXBlO1xuICAgIGlmICgodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ2FycmF5JykgJiYgZGVjbGFyYXRpb24udHJhbnNpdGlvbmFibGUpIHtcbiAgICAgICAgdGhpcy5pbnRlcnAgPSBpbnRlcnBab29tVHJhbnNpdGlvbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW50ZXJwID0gaW50ZXJwb2xhdGVbdHlwZV07XG4gICAgfVxuXG4gICAgdGhpcy5vbGRUcmFuc2l0aW9uID0gb2xkVHJhbnNpdGlvbjtcbiAgICB0aGlzLmR1cmF0aW9uID0gdmFsdWUuZHVyYXRpb24gfHwgMDtcbiAgICB0aGlzLmRlbGF5ID0gdmFsdWUuZGVsYXkgfHwgMDtcblxuICAgIGlmICghdGhpcy5pbnN0YW50KCkpIHtcbiAgICAgICAgdGhpcy5lbmRUaW1lID0gdGhpcy5zdGFydFRpbWUgKyB0aGlzLmR1cmF0aW9uICsgdGhpcy5kZWxheTtcbiAgICAgICAgdGhpcy5lYXNlID0gdXRpbC5lYXNlQ3ViaWNJbk91dDtcbiAgICB9XG5cbiAgICBpZiAob2xkVHJhbnNpdGlvbiAmJiBvbGRUcmFuc2l0aW9uLmVuZFRpbWUgPD0gdGhpcy5zdGFydFRpbWUpIHtcbiAgICAgICAgLy8gT2xkIHRyYW5zaXRpb24gaXMgZG9uZSBydW5uaW5nLCBzbyB3ZSBjYW5cbiAgICAgICAgLy8gZGVsZXRlIGl0cyByZWZlcmVuY2UgdG8gaXRzIG9sZCB0cmFuc2l0aW9uLlxuXG4gICAgICAgIGRlbGV0ZSBvbGRUcmFuc2l0aW9uLm9sZFRyYW5zaXRpb247XG4gICAgfVxufVxuXG5TdHlsZVRyYW5zaXRpb24ucHJvdG90eXBlLmluc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMub2xkVHJhbnNpdGlvbiB8fCAhdGhpcy5pbnRlcnAgfHwgKHRoaXMuZHVyYXRpb24gPT09IDAgJiYgdGhpcy5kZWxheSA9PT0gMCk7XG59O1xuXG4vKlxuICogUmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgdHJhbnNpdGlvbmluZyBwcm9wZXJ0eSBhdCB6b29tIGxldmVsIGB6YCBhbmQgb3B0aW9uYWwgdGltZSBgdGBcbiAqL1xuU3R5bGVUcmFuc2l0aW9uLnByb3RvdHlwZS5hdCA9IGZ1bmN0aW9uKHosIHpvb21IaXN0b3J5LCB0KSB7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLmRlY2xhcmF0aW9uLmNhbGN1bGF0ZSh6LCB6b29tSGlzdG9yeSwgdGhpcy5kdXJhdGlvbik7XG5cbiAgICBpZiAodGhpcy5pbnN0YW50KCkpIHJldHVybiB2YWx1ZTtcblxuICAgIHQgPSB0IHx8IERhdGUubm93KCk7XG5cbiAgICBpZiAodCA8IHRoaXMuZW5kVGltZSkge1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm9sZFRyYW5zaXRpb24uYXQoeiwgem9vbUhpc3RvcnksIHRoaXMuc3RhcnRUaW1lKTtcbiAgICAgICAgdmFyIGVhc2VkID0gdGhpcy5lYXNlKCh0IC0gdGhpcy5zdGFydFRpbWUgLSB0aGlzLmRlbGF5KSAvIHRoaXMuZHVyYXRpb24pO1xuICAgICAgICB2YWx1ZSA9IHRoaXMuaW50ZXJwKG9sZFZhbHVlLCB2YWx1ZSwgZWFzZWQpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcblxufTtcblxuZnVuY3Rpb24gaW50ZXJwWm9vbVRyYW5zaXRpb25lZChmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGZyb20udG8sXG4gICAgICAgIGZyb21TY2FsZTogZnJvbS50b1NjYWxlLFxuICAgICAgICB0bzogdG8udG8sXG4gICAgICAgIHRvU2NhbGU6IHRvLnRvU2NhbGUsXG4gICAgICAgIHQ6IHRcbiAgICB9O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuY2hvcjtcblxuZnVuY3Rpb24gQW5jaG9yKHgsIHksIGFuZ2xlLCBzZWdtZW50KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcblxuICAgIGlmIChzZWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDtcbiAgICB9XG59XG5cbkFuY2hvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBvaW50LnByb3RvdHlwZSk7XG5cbkFuY2hvci5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IEFuY2hvcih0aGlzLngsIHRoaXMueSwgdGhpcy5hbmdsZSwgdGhpcy5zZWdtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQmluUGFjaztcbmZ1bmN0aW9uIEJpblBhY2sod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLmZyZWUgPSBbeyB4OiAwLCB5OiAwLCB3OiB3aWR0aCwgaDogaGVpZ2h0IH1dO1xufVxuXG4vKipcbiAqIFNpbXBsZSBhbGdvcml0aG0gdG8gcmVjdXJzaXZlbHkgbWVyZ2UgdGhlIG5ld2x5IHJlbGVhc2VkIGNlbGwgd2l0aCBpdHNcbiAqIG5laWdoYm9yLiBUaGlzIGRvZXNuJ3QgbWVyZ2UgbW9yZSB0aGFuIHR3byBjZWxscyBhdCBhIHRpbWUsIGFuZCBmYWlsc1xuICogZm9yIGNvbXBsaWNhdGVkIG1lcmdlcy5cbiAqIEBwcml2YXRlXG4gKi9cbkJpblBhY2sucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbihyZWN0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmZyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmZyZWVbaV07XG5cbiAgICAgICAgaWYgKGZyZWUueSA9PT0gcmVjdC55ICYmIGZyZWUuaCA9PT0gcmVjdC5oICYmIGZyZWUueCArIGZyZWUudyA9PT0gcmVjdC54KSB7XG4gICAgICAgICAgICBmcmVlLncgKz0gcmVjdC53O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZnJlZS54ID09PSByZWN0LnggJiYgZnJlZS53ID09PSByZWN0LncgJiYgZnJlZS55ICsgZnJlZS5oID09PSByZWN0LnkpIHtcbiAgICAgICAgICAgIGZyZWUuaCArPSByZWN0Lmg7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWN0LnkgPT09IGZyZWUueSAmJiByZWN0LmggPT09IGZyZWUuaCAmJiByZWN0LnggKyByZWN0LncgPT09IGZyZWUueCkge1xuICAgICAgICAgICAgZnJlZS54ID0gcmVjdC54O1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcblxuICAgICAgICB9IGVsc2UgaWYgKHJlY3QueCA9PT0gZnJlZS54ICYmIHJlY3QudyA9PT0gZnJlZS53ICYmIHJlY3QueSArIHJlY3QuaCA9PT0gZnJlZS55KSB7XG4gICAgICAgICAgICBmcmVlLnkgPSByZWN0Lnk7XG4gICAgICAgICAgICBmcmVlLmggKz0gcmVjdC5oO1xuXG4gICAgICAgIH0gZWxzZSBjb250aW51ZTtcblxuICAgICAgICB0aGlzLmZyZWUuc3BsaWNlKGksIDEpO1xuICAgICAgICB0aGlzLnJlbGVhc2UoZnJlZSk7XG4gICAgICAgIHJldHVybjtcblxuICAgIH1cbiAgICB0aGlzLmZyZWUucHVzaChyZWN0KTtcbn07XG5cbkJpblBhY2sucHJvdG90eXBlLmFsbG9jYXRlID0gZnVuY3Rpb24od2lkdGgsIGhlaWdodCkge1xuICAgIC8vIEZpbmQgdGhlIHNtYWxsZXN0IGZyZWUgcmVjdCBhbmdsZVxuICAgIHZhciByZWN0ID0geyB4OiBJbmZpbml0eSwgeTogSW5maW5pdHksIHc6IEluZmluaXR5LCBoOiBJbmZpbml0eSB9O1xuICAgIHZhciBzbWFsbGVzdCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZWYgPSB0aGlzLmZyZWVbaV07XG4gICAgICAgIGlmICh3aWR0aCA8PSByZWYudyAmJiBoZWlnaHQgPD0gcmVmLmggJiYgcmVmLnkgPD0gcmVjdC55ICYmIHJlZi54IDw9IHJlY3QueCkge1xuICAgICAgICAgICAgcmVjdCA9IHJlZjtcbiAgICAgICAgICAgIHNtYWxsZXN0ID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzbWFsbGVzdCA8IDApIHtcbiAgICAgICAgLy8gVGhlcmUncyBubyBzcGFjZSBsZWZ0IGZvciB0aGlzIGNoYXIuXG4gICAgICAgIHJldHVybiB7IHg6IC0xLCB5OiAtMSB9O1xuICAgIH1cblxuICAgIHRoaXMuZnJlZS5zcGxpY2Uoc21hbGxlc3QsIDEpO1xuXG4gICAgLy8gU2hvcnRlci9Mb25nZXIgQXhpcyBTcGxpdCBSdWxlIChTQVMpXG4gICAgLy8gaHR0cDovL2NsYi5kZW1vbi5maS9maWxlcy9SZWN0YW5nbGVCaW5QYWNrLnBkZiBwLiAxNVxuICAgIC8vIElnbm9yZSB0aGUgZGltZW5zaW9uIG9mIFIgYW5kIGp1c3Qgc3BsaXQgbG9uZyB0aGUgc2hvcnRlciBkaW1lbnNpb25cbiAgICAvLyBTZWUgQWxzbzogaHR0cDovL3d3dy5jcy5wcmluY2V0b24uZWR1L35jaGF6ZWxsZS9wdWJzL2JsYmlucGFja2luZy5wZGZcbiAgICBpZiAocmVjdC53IDwgcmVjdC5oKSB7XG4gICAgICAgIC8vIHNwbGl0IGhvcml6b250YWxseVxuICAgICAgICAvLyArLS0rLS0tK1xuICAgICAgICAvLyB8X198X19ffCAgPC0tIGIxXG4gICAgICAgIC8vICstLS0tLS0rICA8LS0gYjJcbiAgICAgICAgaWYgKHJlY3QudyA+IHdpZHRoKSB0aGlzLmZyZWUucHVzaCh7IHg6IHJlY3QueCArIHdpZHRoLCB5OiByZWN0LnksIHc6IHJlY3QudyAtIHdpZHRoLCBoOiBoZWlnaHQgfSk7XG4gICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHJlY3QudywgaDogcmVjdC5oIC0gaGVpZ2h0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNwbGl0IHZlcnRpY2FsbHlcbiAgICAgICAgLy8gKy0tKy0tLStcbiAgICAgICAgLy8gfF9ffCAgIHwgPC0tIGIxXG4gICAgICAgIC8vICstLXwtLS0rIDwtLSBiMlxuICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IHJlY3QuaCB9KTtcbiAgICAgICAgaWYgKHJlY3QuaCA+IGhlaWdodCkgdGhpcy5mcmVlLnB1c2goeyB4OiByZWN0LngsIHk6IHJlY3QueSArIGhlaWdodCwgdzogd2lkdGgsIGg6IHJlY3QuaCAtIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB4OiByZWN0LngsIHk6IHJlY3QueSwgdzogd2lkdGgsIGg6IGhlaWdodCB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjaGVja01heEFuZ2xlO1xuXG5mdW5jdGlvbiBjaGVja01heEFuZ2xlKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIHdpbmRvd1NpemUsIG1heEFuZ2xlKSB7XG5cbiAgICAvLyBob3Jpem9udGFsIGxhYmVscyBhbHdheXMgcGFzc1xuICAgIGlmIChhbmNob3Iuc2VnbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBwID0gYW5jaG9yO1xuICAgIHZhciBpbmRleCA9IGFuY2hvci5zZWdtZW50ICsgMTtcbiAgICB2YXIgYW5jaG9yRGlzdGFuY2UgPSAwO1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPiAtbGFiZWxMZW5ndGggLyAyKSB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIGlmIChpbmRleCA8IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICBhbmNob3JEaXN0YW5jZSAtPSBsaW5lW2luZGV4XS5kaXN0KHApO1xuICAgICAgICBwID0gbGluZVtpbmRleF07XG4gICAgfVxuXG4gICAgYW5jaG9yRGlzdGFuY2UgKz0gbGluZVtpbmRleF0uZGlzdChsaW5lW2luZGV4ICsgMV0pO1xuICAgIGluZGV4Kys7XG5cbiAgICAvLyBzdG9yZSByZWNlbnQgY29ybmVycyBhbmQgdGhlaXIgdG90YWwgYW5nbGUgZGlmZmVyZW5jZVxuICAgIHZhciByZWNlbnRDb3JuZXJzID0gW107XG4gICAgdmFyIHJlY2VudEFuZ2xlRGVsdGEgPSAwO1xuXG4gICAgLy8gbW92ZSBmb3J3YXJkcyBieSB0aGUgbGVuZ3RoIG9mIHRoZSBsYWJlbCBhbmQgY2hlY2sgYW5nbGVzIGFsb25nIHRoZSB3YXlcbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPCBsYWJlbExlbmd0aCAvIDIpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2luZGV4IC0gMV07XG4gICAgICAgIHZhciBjdXJyZW50ID0gbGluZVtpbmRleF07XG4gICAgICAgIHZhciBuZXh0ID0gbGluZVtpbmRleCArIDFdO1xuXG4gICAgICAgIC8vIHRoZXJlIGlzbid0IGVub3VnaCByb29tIGZvciB0aGUgbGFiZWwgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGxpbmVcbiAgICAgICAgaWYgKCFuZXh0KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIGFuZ2xlRGVsdGEgPSBwcmV2LmFuZ2xlVG8oY3VycmVudCkgLSBjdXJyZW50LmFuZ2xlVG8obmV4dCk7XG4gICAgICAgIC8vIHJlc3RyaWN0IGFuZ2xlIHRvIC1waS4ucGkgcmFuZ2VcbiAgICAgICAgYW5nbGVEZWx0YSA9ICgoYW5nbGVEZWx0YSArIDMgKiBNYXRoLlBJKSAlIChNYXRoLlBJICogMikpIC0gTWF0aC5QSTtcblxuICAgICAgICByZWNlbnRDb3JuZXJzLnB1c2goe1xuICAgICAgICAgICAgZGlzdGFuY2U6IGFuY2hvckRpc3RhbmNlLFxuICAgICAgICAgICAgYW5nbGVEZWx0YTogYW5nbGVEZWx0YVxuICAgICAgICB9KTtcbiAgICAgICAgcmVjZW50QW5nbGVEZWx0YSArPSBhbmdsZURlbHRhO1xuXG4gICAgICAgIC8vIHJlbW92ZSBjb3JuZXJzIHRoYXQgYXJlIGZhciBlbm91Z2ggYXdheSBmcm9tIHRoZSBsaXN0IG9mIHJlY2VudCBhbmNob3JzXG4gICAgICAgIHdoaWxlIChhbmNob3JEaXN0YW5jZSAtIHJlY2VudENvcm5lcnNbMF0uZGlzdGFuY2UgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICByZWNlbnRBbmdsZURlbHRhIC09IHJlY2VudENvcm5lcnMuc2hpZnQoKS5hbmdsZURlbHRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHN1bSBvZiBhbmdsZXMgd2l0aGluIHRoZSB3aW5kb3cgYXJlYSBleGNlZWRzIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuIGNoZWNrIGZhaWxzLlxuICAgICAgICBpZiAoTWF0aC5hYnMocmVjZW50QW5nbGVEZWx0YSkgPiBtYXhBbmdsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGluZGV4Kys7XG4gICAgICAgIGFuY2hvckRpc3RhbmNlICs9IGN1cnJlbnQuZGlzdChuZXh0KTtcbiAgICB9XG5cbiAgICAvLyBubyBwYXJ0IG9mIHRoZSBsaW5lIGhhZCBhbiBhbmdsZSBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gYWxsb3dlZC4gY2hlY2sgcGFzc2VzLlxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsaXBMaW5lO1xuXG5mdW5jdGlvbiBjbGlwTGluZShsaW5lcywgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgY2xpcHBlZExpbmVzID0gW107XG5cbiAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxpbmVzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgIHZhciBsaW5lID0gbGluZXNbbF07XG4gICAgICAgIHZhciBjbGlwcGVkTGluZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcDAgPSBsaW5lW2ldO1xuICAgICAgICAgICAgdmFyIHAxID0gbGluZVtpICsgMV07XG5cblxuICAgICAgICAgICAgaWYgKHAwLnggPCB4MSAmJiBwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueCA8IHgxKSB7XG4gICAgICAgICAgICAgICAgcDAgPSBuZXcgUG9pbnQoeDEsIHAwLnkgKyAocDEueSAtIHAwLnkpICogKCh4MSAtIHAwLngpIC8gKHAxLnggLSBwMC54KSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MSwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgxIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55IDwgeTEgJiYgcDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnkgPCB5MSkge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MSAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgcDEgPSBuZXcgUG9pbnQocDAueCArIChwMS54IC0gcDAueCkgKiAoKHkxIC0gcDAueSkgLyAocDEueSAtIHAwLnkpKSwgeTEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocDAueCA+PSB4MiAmJiBwMS54ID49IHgyKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMCA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAxLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55ID49IHkyICYmIHAxLnkgPj0geTIpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAxID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFjbGlwcGVkTGluZSB8fCAhcDAuZXF1YWxzKGNsaXBwZWRMaW5lW2NsaXBwZWRMaW5lLmxlbmd0aCAtIDFdKSkge1xuICAgICAgICAgICAgICAgIGNsaXBwZWRMaW5lID0gW3AwXTtcbiAgICAgICAgICAgICAgICBjbGlwcGVkTGluZXMucHVzaChjbGlwcGVkTGluZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNsaXBwZWRMaW5lLnB1c2gocDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWRMaW5lcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3g7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveChhbmNob3IsIHgxLCB5MSwgeDIsIHkyLCBtYXhTY2FsZSkge1xuICAgIC8vIHRoZSBib3ggaXMgY2VudGVyZWQgYXJvdW5kIHRoZSBhbmNob3IgcG9pbnRcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcblxuICAgIC8vIGRpc3RhbmNlcyB0byB0aGUgZWRnZXMgZnJvbSB0aGUgYW5jaG9yXG4gICAgdGhpcy54MSA9IHgxO1xuICAgIHRoaXMueTEgPSB5MTtcbiAgICB0aGlzLngyID0geDI7XG4gICAgdGhpcy55MiA9IHkyO1xuXG4gICAgLy8gdGhlIGJveCBpcyBvbmx5IHZhbGlkIGZvciBzY2FsZXMgPCBtYXhTY2FsZS5cbiAgICAvLyBUaGUgYm94IGRvZXMgbm90IGJsb2NrIG90aGVyIGJveGVzIGF0IHNjYWxlcyA+PSBtYXhTY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG5cbiAgICAvLyB0aGUgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIGNhbiBmaXJzdCBiZSBzaG93blxuICAgIHRoaXMucGxhY2VtZW50U2NhbGUgPSAwO1xuXG4gICAgLy8gcm90YXRlZCBhbmQgc2NhbGVkIGJib3ggdXNlZCBmb3IgaW5kZXhpbmdcbiAgICB0aGlzWzBdID0gdGhpc1sxXSA9IHRoaXNbMl0gPSB0aGlzWzNdID0gMDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbGxpc2lvbkJveCA9IHJlcXVpcmUoJy4vY29sbGlzaW9uX2JveCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxpc2lvbkZlYXR1cmU7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkZlYXR1cmUobGluZSwgYW5jaG9yLCBzaGFwZWQsIGJveFNjYWxlLCBwYWRkaW5nLCBhbGlnbkxpbmUpIHtcblxuICAgIHZhciB5MSA9IHNoYXBlZC50b3AgKiBib3hTY2FsZSAtIHBhZGRpbmc7XG4gICAgdmFyIHkyID0gc2hhcGVkLmJvdHRvbSAqIGJveFNjYWxlICsgcGFkZGluZztcbiAgICB2YXIgeDEgPSBzaGFwZWQubGVmdCAqIGJveFNjYWxlIC0gcGFkZGluZztcbiAgICB2YXIgeDIgPSBzaGFwZWQucmlnaHQgKiBib3hTY2FsZSArIHBhZGRpbmc7XG5cbiAgICB0aGlzLmJveGVzID0gW107XG5cbiAgICBpZiAoYWxpZ25MaW5lKSB7XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IHkyIC0geTE7XG4gICAgICAgIHZhciBsZW5ndGggPSB4MiAtIHgxO1xuXG4gICAgICAgIGlmIChoZWlnaHQgPD0gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIHNldCBtaW5pbXVtIGJveCBoZWlnaHQgdG8gYXZvaWQgdmVyeSBtYW55IHNtYWxsIGxhYmVsc1xuICAgICAgICBoZWlnaHQgPSBNYXRoLm1heCgxMCAqIGJveFNjYWxlLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuYmJveGlmeUxhYmVsKGxpbmUsIGFuY2hvciwgbGVuZ3RoLCBoZWlnaHQpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ib3hlcy5wdXNoKG5ldyBDb2xsaXNpb25Cb3goYW5jaG9yLCB4MSwgeTEsIHgyLCB5MiwgSW5maW5pdHkpKTtcbiAgICB9XG59XG5cbkNvbGxpc2lvbkZlYXR1cmUucHJvdG90eXBlLmJib3hpZnlMYWJlbCA9IGZ1bmN0aW9uKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIGJveFNpemUpIHtcbiAgICB2YXIgc3RlcCA9IGJveFNpemUgLyAyO1xuICAgIHZhciBuQm94ZXMgPSBNYXRoLmZsb29yKGxhYmVsTGVuZ3RoIC8gc3RlcCk7XG5cbiAgICAvLyBvZmZzZXQgdGhlIGNlbnRlciBvZiB0aGUgZmlyc3QgYm94IGJ5IGhhbGYgYSBib3ggc28gdGhhdCB0aGUgZWRnZSBvZiB0aGVcbiAgICAvLyBib3ggaXMgYXQgdGhlIGVkZ2Ugb2YgdGhlIGxhYmVsLlxuICAgIHZhciBmaXJzdEJveE9mZnNldCA9IC1ib3hTaXplIC8gMjtcblxuICAgIHZhciBiYm94ZXMgPSB0aGlzLmJveGVzO1xuXG4gICAgdmFyIHAgPSBhbmNob3I7XG4gICAgdmFyIGluZGV4ID0gYW5jaG9yLnNlZ21lbnQgKyAxO1xuICAgIHZhciBhbmNob3JEaXN0YW5jZSA9IGZpcnN0Qm94T2Zmc2V0O1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICBkbyB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIC8vIGNoZWNrTWF4QW5nbGUgc2hvdWxkIGhhdmUgYWxyZWFkeSBjYXVnaHQgdGhpc1xuICAgICAgICBpZiAoaW5kZXggPCAwKSByZXR1cm4gYmJveGVzO1xuXG4gICAgICAgIGFuY2hvckRpc3RhbmNlIC09IGxpbmVbaW5kZXhdLmRpc3QocCk7XG4gICAgICAgIHAgPSBsaW5lW2luZGV4XTtcbiAgICB9IHdoaWxlIChhbmNob3JEaXN0YW5jZSA+IC1sYWJlbExlbmd0aCAvIDIpO1xuXG4gICAgdmFyIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5Cb3hlczsgaSsrKSB7XG4gICAgICAgIC8vIHRoZSBkaXN0YW5jZSB0aGUgYm94IHdpbGwgYmUgZnJvbSB0aGUgYW5jaG9yXG4gICAgICAgIHZhciBib3hEaXN0YW5jZVRvQW5jaG9yID0gLWxhYmVsTGVuZ3RoIC8gMiArIGkgKiBzdGVwO1xuXG4gICAgICAgIC8vIHRoZSBib3ggaXMgbm90IG9uIHRoZSBjdXJyZW50IHNlZ21lbnQuIE1vdmUgdG8gdGhlIG5leHQgc2VnbWVudC5cbiAgICAgICAgd2hpbGUgKGFuY2hvckRpc3RhbmNlICsgc2VnbWVudExlbmd0aCA8IGJveERpc3RhbmNlVG9BbmNob3IpIHtcbiAgICAgICAgICAgIGFuY2hvckRpc3RhbmNlICs9IHNlZ21lbnRMZW5ndGg7XG4gICAgICAgICAgICBpbmRleCsrO1xuXG4gICAgICAgICAgICAvLyBUaGVyZSBpc24ndCBlbm91Z2ggcm9vbSBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgbGluZS5cbiAgICAgICAgICAgIGlmIChpbmRleCArIDEgPj0gbGluZS5sZW5ndGgpIHJldHVybiBiYm94ZXM7XG5cbiAgICAgICAgICAgIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgZGlzdGFuY2UgdGhlIGJveCB3aWxsIGJlIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc2VnbWVudFxuICAgICAgICB2YXIgc2VnbWVudEJveERpc3RhbmNlID0gYm94RGlzdGFuY2VUb0FuY2hvciAtIGFuY2hvckRpc3RhbmNlO1xuXG4gICAgICAgIHZhciBwMCA9IGxpbmVbaW5kZXhdO1xuICAgICAgICB2YXIgcDEgPSBsaW5lW2luZGV4ICsgMV07XG4gICAgICAgIHZhciBib3hBbmNob3IgPSBwMS5zdWIocDApLl91bml0KCkuX211bHQoc2VnbWVudEJveERpc3RhbmNlKS5fYWRkKHAwKTtcblxuICAgICAgICB2YXIgZGlzdGFuY2VUb0lubmVyRWRnZSA9IE1hdGgubWF4KE1hdGguYWJzKGJveERpc3RhbmNlVG9BbmNob3IgLSBmaXJzdEJveE9mZnNldCkgLSBzdGVwIC8gMiwgMCk7XG4gICAgICAgIHZhciBtYXhTY2FsZSA9IGxhYmVsTGVuZ3RoIC8gMiAvIGRpc3RhbmNlVG9Jbm5lckVkZ2U7XG5cbiAgICAgICAgYmJveGVzLnB1c2gobmV3IENvbGxpc2lvbkJveChib3hBbmNob3IsIC1ib3hTaXplIC8gMiwgLWJveFNpemUgLyAyLCBib3hTaXplIC8gMiwgYm94U2l6ZSAvIDIsIG1heFNjYWxlKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJib3hlcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByYnVzaCA9IHJlcXVpcmUoJ3JidXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sbGlzaW9uVGlsZTtcblxuZnVuY3Rpb24gQ29sbGlzaW9uVGlsZSh6b29tLCB0aWxlRXh0ZW50LCB0aWxlU2l6ZSkge1xuICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgdGhpcy50aWxlUGl4ZWxSYXRpbyA9IHRpbGVFeHRlbnQgLyB0aWxlU2l6ZTtcbn1cblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWluU2NhbGUgPSAwLjI1O1xuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWF4U2NhbGUgPSAyO1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCkge1xuICAgIHRoaXMudHJlZSA9IHJidXNoKCk7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHRoaXMucm90YXRpb25NYXRyaXggPSBbY29zLCAtc2luLCBzaW4sIGNvc107XG5cbiAgICAvLyBTdHJldGNoIGJveGVzIGluIHkgZGlyZWN0aW9uIHRvIGFjY291bnQgZm9yIHRoZSBtYXAgdGlsdC5cbiAgICB0aGlzLnlTdHJldGNoID0gMSAvIE1hdGguY29zKHBpdGNoIC8gMTgwICogTWF0aC5QSSk7XG5cbiAgICAvLyBUaGUgYW1vdW50IHRoZSBtYXAgaXMgc3F1aXNoZWQgZGVwZW5kcyBvbiB0aGUgeSBwb3NpdGlvbi5cbiAgICAvLyBTb3J0IG9mIGFjY291bnQgZm9yIHRoaXMgYnkgbWFraW5nIGFsbCBib3hlcyBhIGJpdCBiaWdnZXIuXG4gICAgdGhpcy55U3RyZXRjaCA9IE1hdGgucG93KHRoaXMueVN0cmV0Y2gsIDEuMyk7XG59O1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5wbGFjZUZlYXR1cmUgPSBmdW5jdGlvbihmZWF0dXJlKSB7XG5cbiAgICB2YXIgbWluUGxhY2VtZW50U2NhbGUgPSB0aGlzLm1pblNjYWxlO1xuICAgIHZhciByb3RhdGlvbk1hdHJpeCA9IHRoaXMucm90YXRpb25NYXRyaXg7XG4gICAgdmFyIHlTdHJldGNoID0gdGhpcy55U3RyZXRjaDtcblxuICAgIGZvciAodmFyIGIgPSAwOyBiIDwgZmVhdHVyZS5ib3hlcy5sZW5ndGg7IGIrKykge1xuXG4gICAgICAgIHZhciBib3ggPSBmZWF0dXJlLmJveGVzW2JdO1xuXG4gICAgICAgIHZhciBhbmNob3IgPSBib3guYW5jaG9yLm1hdE11bHQocm90YXRpb25NYXRyaXgpO1xuICAgICAgICB2YXIgeCA9IGFuY2hvci54O1xuICAgICAgICB2YXIgeSA9IGFuY2hvci55O1xuXG4gICAgICAgIGJveFswXSA9IHggKyBib3gueDE7XG4gICAgICAgIGJveFsxXSA9IHkgKyBib3gueTEgKiB5U3RyZXRjaDtcbiAgICAgICAgYm94WzJdID0geCArIGJveC54MjtcbiAgICAgICAgYm94WzNdID0geSArIGJveC55MiAqIHlTdHJldGNoO1xuXG4gICAgICAgIHZhciBibG9ja2luZ0JveGVzID0gdGhpcy50cmVlLnNlYXJjaChib3gpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tpbmdCb3hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJsb2NraW5nID0gYmxvY2tpbmdCb3hlc1tpXTtcbiAgICAgICAgICAgIHZhciBibG9ja2luZ0FuY2hvciA9IGJsb2NraW5nLmFuY2hvci5tYXRNdWx0KHJvdGF0aW9uTWF0cml4KTtcblxuICAgICAgICAgICAgLy8gRmluZCB0aGUgbG93ZXN0IHNjYWxlIGF0IHdoaWNoIHRoZSB0d28gYm94ZXMgY2FuIGZpdCBzaWRlIGJ5IHNpZGUgd2l0aG91dCBvdmVybGFwcGluZy5cbiAgICAgICAgICAgIC8vIE9yaWdpbmFsIGFsZ29yaXRobTpcbiAgICAgICAgICAgIHZhciBzMSA9IChibG9ja2luZy54MSAtIGJveC54MikgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSBsZWZ0IG9mIG9sZCBib3hcbiAgICAgICAgICAgIHZhciBzMiA9IChibG9ja2luZy54MiAtIGJveC54MSkgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSByaWdodCBvZiBvbGQgYm94XG4gICAgICAgICAgICB2YXIgczMgPSAoYmxvY2tpbmcueTEgLSBib3gueTIpICogeVN0cmV0Y2ggLyAoeSAtIGJsb2NraW5nQW5jaG9yLnkpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSB0b3Agb2Ygb2xkIGJveFxuICAgICAgICAgICAgdmFyIHM0ID0gKGJsb2NraW5nLnkyIC0gYm94LnkxKSAqIHlTdHJldGNoIC8gKHkgLSBibG9ja2luZ0FuY2hvci55KTsgLy8gc2NhbGUgYXQgd2hpY2ggbmV3IGJveCBpcyB0byB0aGUgYm90dG9tIG9mIG9sZCBib3hcblxuICAgICAgICAgICAgaWYgKGlzTmFOKHMxKSB8fCBpc05hTihzMikpIHMxID0gczIgPSAxO1xuICAgICAgICAgICAgaWYgKGlzTmFOKHMzKSB8fCBpc05hTihzNCkpIHMzID0gczQgPSAxO1xuXG4gICAgICAgICAgICB2YXIgY29sbGlzaW9uRnJlZVNjYWxlID0gTWF0aC5taW4oTWF0aC5tYXgoczEsIHMyKSwgTWF0aC5tYXgoczMsIHM0KSk7XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBibG9ja2luZy5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIEFmdGVyIGEgYm94J3MgbWF4U2NhbGUgdGhlIGxhYmVsIGhhcyBzaHJ1bmsgZW5vdWdoIHRoYXQgdGhlIGJveCBpcyBubyBsb25nZXIgbmVlZGVkIHRvIGNvdmVyIGl0LFxuICAgICAgICAgICAgICAgIC8vIHNvIHVuYmxvY2sgdGhlIG5ldyBib3ggYXQgdGhlIHNjYWxlIHRoYXQgdGhlIG9sZCBib3ggZGlzYXBwZWFycy5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBibG9ja2luZy5tYXhTY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbGxpc2lvbkZyZWVTY2FsZSA+IGJveC5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBib3ggY2FuIG9ubHkgYmUgc2hvd24gYWZ0ZXIgaXQgaXMgdmlzaWJsZSwgdGhlbiB0aGUgYm94IGNhbiBuZXZlciBiZSBzaG93bi5cbiAgICAgICAgICAgICAgICAvLyBCdXQgdGhlIGxhYmVsIGNhbiBiZSBzaG93biBhZnRlciB0aGlzIGJveCBpcyBub3QgdmlzaWJsZS5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBib3gubWF4U2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBtaW5QbGFjZW1lbnRTY2FsZSAmJlxuICAgICAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPj0gYmxvY2tpbmcucGxhY2VtZW50U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGNvbGxpc2lvbiBvY2N1cnMgYXQgYSBsb3dlciBzY2FsZSB0aGFuIHByZXZpb3VzbHkgZm91bmQgY29sbGlzaW9uc1xuICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgY29sbGlzaW9uIG9jY3VycyB3aGlsZSB0aGUgb3RoZXIgbGFiZWwgaXMgdmlzaWJsZVxuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB0aGlzIGlzIHRoZSBsb3dlc3Qgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIHdvbid0IGNvbGxpZGUgd2l0aCBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIG1pblBsYWNlbWVudFNjYWxlID0gY29sbGlzaW9uRnJlZVNjYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPj0gdGhpcy5tYXhTY2FsZSkgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xufTtcblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUuaW5zZXJ0RmVhdHVyZSA9IGZ1bmN0aW9uKGZlYXR1cmUsIG1pblBsYWNlbWVudFNjYWxlKSB7XG5cbiAgICB2YXIgYm94ZXMgPSBmZWF0dXJlLmJveGVzO1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYm94ZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgYm94ZXNba10ucGxhY2VtZW50U2NhbGUgPSBtaW5QbGFjZW1lbnRTY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPCB0aGlzLm1heFNjYWxlKSB7XG4gICAgICAgIHRoaXMudHJlZS5sb2FkKGJveGVzKTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW50ZXJwb2xhdGUgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyk7XG52YXIgQW5jaG9yID0gcmVxdWlyZSgnLi4vc3ltYm9sL2FuY2hvcicpO1xudmFyIGNoZWNrTWF4QW5nbGUgPSByZXF1aXJlKCcuL2NoZWNrX21heF9hbmdsZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEFuY2hvcnM7XG5cbmZ1bmN0aW9uIGdldEFuY2hvcnMobGluZSwgc3BhY2luZywgbWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgYm94U2NhbGUsIG92ZXJzY2FsaW5nKSB7XG5cbiAgICAvLyBSZXNhbXBsZSBhIGxpbmUgdG8gZ2V0IGFuY2hvciBwb2ludHMgZm9yIGxhYmVscyBhbmQgY2hlY2sgdGhhdCBlYWNoXG4gICAgLy8gcG90ZW50aWFsIGxhYmVsIHBhc3NlcyB0ZXh0LW1heC1hbmdsZSBjaGVjayBhbmQgaGFzIGVub3VnaCBmcm9vbSB0byBmaXRcbiAgICAvLyBvbiB0aGUgbGluZS5cblxuICAgIHZhciBhbmdsZVdpbmRvd1NpemUgPSBzaGFwZWRUZXh0ID9cbiAgICAgICAgMyAvIDUgKiBnbHlwaFNpemUgKiBib3hTY2FsZSA6XG4gICAgICAgIDA7XG5cbiAgICAvLyBPZmZzZXQgdGhlIGZpcnN0IGFuY2hvciBieSBoYWxmIHRoZSBsYWJlbCBsZW5ndGggKG9yIGhhbGYgdGhlIHNwYWNpbmcgZGlzdGFuY2UgZm9yIGljb25zKS5cbiAgICAvLyBBZGQgYSBiaXQgb2YgZXh0cmEgb2Zmc2V0IHRvIGF2b2lkIGNvbGxpc2lvbnMgYXQgVCBpbnRlcnNlY3Rpb25zLlxuICAgIHZhciBsYWJlbExlbmd0aCA9IHNoYXBlZFRleHQgPyBzaGFwZWRUZXh0LnJpZ2h0IC0gc2hhcGVkVGV4dC5sZWZ0IDogc3BhY2luZztcbiAgICB2YXIgZXh0cmFPZmZzZXQgPSBnbHlwaFNpemUgKiAyO1xuICAgIHZhciBvZmZzZXQgPSAoKGxhYmVsTGVuZ3RoIC8gMiArIGV4dHJhT2Zmc2V0KSAqIGJveFNjYWxlICogb3ZlcnNjYWxpbmcpICUgc3BhY2luZztcblxuICAgIHJldHVybiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoICogYm94U2NhbGUsIGZhbHNlKTtcbn1cblxuXG5mdW5jdGlvbiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoLCBwbGFjZUF0TWlkZGxlKSB7XG5cbiAgICB2YXIgZGlzdGFuY2UgPSAwLFxuICAgICAgICBtYXJrZWREaXN0YW5jZSA9IG9mZnNldCA/IG9mZnNldCAtIHNwYWNpbmcgOiAwO1xuXG4gICAgdmFyIGFuY2hvcnMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZS5sZW5ndGggLSAxOyBpKyspIHtcblxuICAgICAgICB2YXIgYSA9IGxpbmVbaV0sXG4gICAgICAgICAgICBiID0gbGluZVtpICsgMV07XG5cbiAgICAgICAgdmFyIHNlZ21lbnREaXN0ID0gYS5kaXN0KGIpLFxuICAgICAgICAgICAgYW5nbGUgPSBiLmFuZ2xlVG8oYSk7XG5cbiAgICAgICAgd2hpbGUgKG1hcmtlZERpc3RhbmNlICsgc3BhY2luZyA8IGRpc3RhbmNlICsgc2VnbWVudERpc3QpIHtcbiAgICAgICAgICAgIG1hcmtlZERpc3RhbmNlICs9IHNwYWNpbmc7XG5cbiAgICAgICAgICAgIHZhciB0ID0gKG1hcmtlZERpc3RhbmNlIC0gZGlzdGFuY2UpIC8gc2VnbWVudERpc3QsXG4gICAgICAgICAgICAgICAgeCA9IGludGVycG9sYXRlKGEueCwgYi54LCB0KSxcbiAgICAgICAgICAgICAgICB5ID0gaW50ZXJwb2xhdGUoYS55LCBiLnksIHQpO1xuXG4gICAgICAgICAgICBpZiAoeCA+PSAwICYmIHggPCA0MDk2ICYmIHkgPj0gMCAmJiB5IDwgNDA5Nikge1xuICAgICAgICAgICAgICAgIHggPSBNYXRoLnJvdW5kKHgpO1xuICAgICAgICAgICAgICAgIHkgPSBNYXRoLnJvdW5kKHkpO1xuICAgICAgICAgICAgICAgIHZhciBhbmNob3IgPSBuZXcgQW5jaG9yKHgsIHksIGFuZ2xlLCBpKTtcblxuICAgICAgICAgICAgICAgIGlmICghYW5nbGVXaW5kb3dTaXplIHx8IGNoZWNrTWF4QW5nbGUobGluZSwgYW5jaG9yLCBsYWJlbExlbmd0aCwgYW5nbGVXaW5kb3dTaXplLCBtYXhBbmdsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9ycy5wdXNoKGFuY2hvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGlzdGFuY2UgKz0gc2VnbWVudERpc3Q7XG4gICAgfVxuXG4gICAgaWYgKCFwbGFjZUF0TWlkZGxlICYmICFhbmNob3JzLmxlbmd0aCkge1xuICAgICAgICAvLyBUaGUgZmlyc3QgYXR0ZW1wdCBhdCBmaW5kaW5nIGFuY2hvcnMgYXQgd2hpY2ggbGFiZWxzIGNhbiBiZSBwbGFjZWQgZmFpbGVkLlxuICAgICAgICAvLyBUcnkgYWdhaW4sIGJ1dCB0aGlzIHRpbWUganVzdCB0cnkgcGxhY2luZyBvbmUgYW5jaG9yIGF0IHRoZSBtaWRkbGUgb2YgdGhlIGxpbmUuXG4gICAgICAgIC8vIFRoaXMgaGFzIHRoZSBtb3N0IGVmZmVjdCBmb3Igc2hvcnQgbGluZXMgaW4gb3ZlcnNjYWxlZCB0aWxlcywgc2luY2UgdGhlXG4gICAgICAgIC8vIGluaXRpYWwgb2Zmc2V0IHVzZWQgaW4gb3ZlcnNjYWxlZCB0aWxlcyBpcyBjYWxjdWxhdGVkIHRvIGFsaWduIGxhYmVscyB3aXRoIHBvc2l0aW9ucyBpblxuICAgICAgICAvLyBwYXJlbnQgdGlsZXMgaW5zdGVhZCBvZiBwbGFjaW5nIHRoZSBsYWJlbCBhcyBjbG9zZSB0byB0aGUgYmVnaW5uaW5nIGFzIHBvc3NpYmxlLlxuICAgICAgICBhbmNob3JzID0gcmVzYW1wbGUobGluZSwgZGlzdGFuY2UgLyAyLCBzcGFjaW5nLCBhbmdsZVdpbmRvd1NpemUsIG1heEFuZ2xlLCBsYWJlbExlbmd0aCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuY2hvcnM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCaW5QYWNrID0gcmVxdWlyZSgnLi9iaW5fcGFjaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoQXRsYXM7XG5mdW5jdGlvbiBHbHlwaEF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW5kZXggPSB7fTtcbiAgICB0aGlzLmlkcyA9IHt9O1xuICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbn1cblxuR2x5cGhBdGxhcy5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGRlYnVnKCkge1xuICAgICAgICByZXR1cm4gJ2NhbnZhcycgaW4gdGhpcztcbiAgICB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgJiYgIXRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuZ2V0R2x5cGhzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdseXBocyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghZ2x5cGhzW25hbWVdKSBnbHlwaHNbbmFtZV0gPSBbXTtcbiAgICAgICAgZ2x5cGhzW25hbWVdLnB1c2goaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBnbHlwaHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5nZXRSZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWN0cyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghcmVjdHNbbmFtZV0pIHJlY3RzW25hbWVdID0ge307XG4gICAgICAgIHJlY3RzW25hbWVdW2lkXSA9IHRoaXMuaW5kZXhba2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5yZW1vdmVHbHlwaHMgPSBmdW5jdGlvbihpZCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmlkcykge1xuXG4gICAgICAgIHZhciBpZHMgPSB0aGlzLmlkc1trZXldO1xuXG4gICAgICAgIHZhciBwb3MgPSBpZHMuaW5kZXhPZihpZCk7XG4gICAgICAgIGlmIChwb3MgPj0gMCkgaWRzLnNwbGljZShwb3MsIDEpO1xuICAgICAgICB0aGlzLmlkc1trZXldID0gaWRzO1xuXG4gICAgICAgIGlmICghaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHJlY3QgPSB0aGlzLmluZGV4W2tleV07XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHJlY3QuaDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5KSArIHJlY3QueDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHJlY3QudzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmJpbi5yZWxlYXNlKHJlY3QpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pbmRleFtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWRzW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHRoaXMudXBkYXRlVGV4dHVyZSh0aGlzLmdsKTtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmFkZEdseXBoID0gZnVuY3Rpb24oaWQsIG5hbWUsIGdseXBoLCBidWZmZXIpIHtcbiAgICBpZiAoIWdseXBoKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignbWlzc2luZyBnbHlwaCcsIGNvZGUsIFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIGtleSA9IG5hbWUgKyBcIiNcIiArIGdseXBoLmlkO1xuXG4gICAgLy8gVGhlIGdseXBoIGlzIGFscmVhZHkgaW4gdGhpcyB0ZXh0dXJlLlxuICAgIGlmICh0aGlzLmluZGV4W2tleV0pIHtcbiAgICAgICAgaWYgKHRoaXMuaWRzW2tleV0uaW5kZXhPZihpZCkgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmlkc1trZXldLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZGV4W2tleV07XG4gICAgfVxuXG4gICAgLy8gVGhlIGdseXBoIGJpdG1hcCBoYXMgemVybyB3aWR0aC5cbiAgICBpZiAoIWdseXBoLmJpdG1hcCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYnVmZmVyZWRXaWR0aCA9IGdseXBoLndpZHRoICsgYnVmZmVyICogMjtcbiAgICB2YXIgYnVmZmVyZWRIZWlnaHQgPSBnbHlwaC5oZWlnaHQgKyBidWZmZXIgKiAyO1xuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuICAgIHZhciBwYWNrV2lkdGggPSBidWZmZXJlZFdpZHRoICsgMiAqIHBhZGRpbmc7XG4gICAgdmFyIHBhY2tIZWlnaHQgPSBidWZmZXJlZEhlaWdodCArIDIgKiBwYWRkaW5nO1xuXG4gICAgLy8gSW5jcmVhc2UgdG8gbmV4dCBudW1iZXIgZGl2aXNpYmxlIGJ5IDQsIGJ1dCBhdCBsZWFzdCAxLlxuICAgIC8vIFRoaXMgaXMgc28gd2UgY2FuIHNjYWxlIGRvd24gdGhlIHRleHR1cmUgY29vcmRpbmF0ZXMgYW5kIHBhY2sgdGhlbVxuICAgIC8vIGludG8gMiBieXRlcyByYXRoZXIgdGhhbiA0IGJ5dGVzLlxuICAgIHBhY2tXaWR0aCArPSAoNCAtIHBhY2tXaWR0aCAlIDQpO1xuICAgIHBhY2tIZWlnaHQgKz0gKDQgLSBwYWNrSGVpZ2h0ICUgNCk7XG5cbiAgICB2YXIgcmVjdCA9IHRoaXMuYmluLmFsbG9jYXRlKHBhY2tXaWR0aCwgcGFja0hlaWdodCk7XG4gICAgaWYgKHJlY3QueCA8IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdnbHlwaCBiaXRtYXAgb3ZlcmZsb3cnKTtcbiAgICAgICAgcmV0dXJuIHsgZ2x5cGg6IGdseXBoLCByZWN0OiBudWxsIH07XG4gICAgfVxuXG4gICAgdGhpcy5pbmRleFtrZXldID0gcmVjdDtcbiAgICB0aGlzLmlkc1trZXldID0gW2lkXTtcblxuICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgdmFyIHNvdXJjZSA9IGdseXBoLmJpdG1hcDtcbiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGJ1ZmZlcmVkSGVpZ2h0OyB5KyspIHtcbiAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5ICsgcGFkZGluZykgKyByZWN0LnggKyBwYWRkaW5nO1xuICAgICAgICB2YXIgeTIgPSBidWZmZXJlZFdpZHRoICogeTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBidWZmZXJlZFdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gc291cmNlW3kyICsgeF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcblxuICAgIHJldHVybiByZWN0O1xufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgdGhpcy5nbCA9IGdsO1xuICAgIGlmICghdGhpcy50ZXh0dXJlKSB7XG4gICAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuQUxQSEEsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCAwLCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgIH1cbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLnVwZGF0ZVRleHR1cmUgPSBmdW5jdGlvbihnbCkge1xuICAgIHRoaXMuYmluZChnbCk7XG4gICAgaWYgKHRoaXMuZGlydHkpIHtcblxuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy5kYXRhKTtcblxuICAgICAgICAvLyBERUJVR1xuICAgICAgICBpZiAodGhpcy5jdHgpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gdGhpcy5jdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKywgaiArPSA0KSB7XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2pdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICAgICAgICAgIGRhdGEuZGF0YVtqICsgMV0gPSB0aGlzLmRhdGFbaV07XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2ogKyAyXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaiArIDNdID0gMjU1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54LCBmcmVlLnksIGZyZWUudywgZnJlZS5oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcblxuICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplR2x5cGhzVVJMO1xudmFyIGdldEFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4JykuZ2V0QXJyYXlCdWZmZXI7XG52YXIgR2x5cGhzID0gcmVxdWlyZSgnLi4vdXRpbC9nbHlwaHMnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoU291cmNlO1xuXG4vKipcbiAqIEEgZ2x5cGggc291cmNlIGhhcyBhIFVSTCBmcm9tIHdoaWNoIHRvIGxvYWQgbmV3IGdseXBocyBhbmQgb3ducyBhIEdseXBoQXRsYXNcbiAqIHRoYXQgc3RvcmVzIGN1cnJlbnRseS1sb2FkZWQgZ2x5cGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgZ2x5cGggdGVtcGxhdGUgdXJsXG4gKiBAcGFyYW0ge09iamVjdH0gZ2x5cGhBdGxhcyBnbHlwaCBhdGxhcyBvYmplY3RcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEdseXBoU291cmNlKHVybCwgZ2x5cGhBdGxhcykge1xuICAgIHRoaXMudXJsID0gdXJsICYmIG5vcm1hbGl6ZVVSTCh1cmwpO1xuICAgIHRoaXMuZ2x5cGhBdGxhcyA9IGdseXBoQXRsYXM7XG4gICAgdGhpcy5zdGFja3MgPSBbXTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcbn1cblxuR2x5cGhTb3VyY2UucHJvdG90eXBlLmdldFNpbXBsZUdseXBocyA9IGZ1bmN0aW9uKGZvbnRzdGFjaywgZ2x5cGhJRHMsIHVpZCwgY2FsbGJhY2spIHtcblxuICAgIGlmICh0aGlzLnN0YWNrc1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10gPSB7fTtcblxuICAgIHZhciBnbHlwaHMgPSB7fTtcblxuICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja107XG4gICAgdmFyIGdseXBoQXRsYXMgPSB0aGlzLmdseXBoQXRsYXM7XG5cbiAgICAvLyB0aGUgbnVtYmVyIG9mIHBpeGVscyB0aGUgc2RmIGJpdG1hcHMgYXJlIHBhZGRlZCBieVxuICAgIHZhciBidWZmZXIgPSAzO1xuXG4gICAgdmFyIG1pc3NpbmcgPSB7fTtcbiAgICB2YXIgcmVtYWluaW5nID0gMDtcbiAgICB2YXIgcmFuZ2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdseXBoSURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnbHlwaElEID0gZ2x5cGhJRHNbaV07XG4gICAgICAgIHJhbmdlID0gTWF0aC5mbG9vcihnbHlwaElEIC8gMjU2KTtcblxuICAgICAgICBpZiAoc3RhY2tbcmFuZ2VdKSB7XG4gICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFja1tyYW5nZV0uZ2x5cGhzW2dseXBoSURdO1xuICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICBpZiAoZ2x5cGgpIGdseXBoc1tnbHlwaElEXSA9IG5ldyBTaW1wbGVHbHlwaChnbHlwaCwgcmVjdCwgYnVmZmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nW3JhbmdlXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1tyYW5nZV0gPSBbXTtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pc3NpbmdbcmFuZ2VdLnB1c2goZ2x5cGhJRCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXJlbWFpbmluZykgY2FsbGJhY2sodW5kZWZpbmVkLCBnbHlwaHMpO1xuXG4gICAgdmFyIG9uUmFuZ2VMb2FkZWQgPSBmdW5jdGlvbihlcnIsIHJhbmdlLCBkYXRhKSB7XG4gICAgICAgIC8vIFRPRE8gbm90IGJlIHNpbGVudCBhYm91dCBlcnJvcnNcbiAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja11bcmFuZ2VdID0gZGF0YS5zdGFja3NbMF07XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdbcmFuZ2VdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdseXBoSUQgPSBtaXNzaW5nW3JhbmdlXVtpXTtcbiAgICAgICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFjay5nbHlwaHNbZ2x5cGhJRF07XG4gICAgICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKGdseXBoKSBnbHlwaHNbZ2x5cGhJRF0gPSBuZXcgU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIGdseXBocyk7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgZm9yICh2YXIgciBpbiBtaXNzaW5nKSB7XG4gICAgICAgIHRoaXMubG9hZFJhbmdlKGZvbnRzdGFjaywgciwgb25SYW5nZUxvYWRlZCk7XG4gICAgfVxufTtcblxuLy8gQSBzaW1wbGlmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnbHlwaCBjb250YWluaW5nIG9ubHkgdGhlIHByb3BlcnRpZXMgbmVlZGVkIGZvciBzaGFwaW5nLlxuZnVuY3Rpb24gU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcikge1xuICAgIHZhciBwYWRkaW5nID0gMTtcbiAgICB0aGlzLmFkdmFuY2UgPSBnbHlwaC5hZHZhbmNlO1xuICAgIHRoaXMubGVmdCA9IGdseXBoLmxlZnQgLSBidWZmZXIgLSBwYWRkaW5nO1xuICAgIHRoaXMudG9wID0gZ2x5cGgudG9wICsgYnVmZmVyICsgcGFkZGluZztcbiAgICB0aGlzLnJlY3QgPSByZWN0O1xufVxuXG5HbHlwaFNvdXJjZS5wcm90b3R5cGUubG9hZFJhbmdlID0gZnVuY3Rpb24oZm9udHN0YWNrLCByYW5nZSwgY2FsbGJhY2spIHtcblxuICAgIGlmIChyYW5nZSAqIDI1NiA+IDY1NTM1KSByZXR1cm4gY2FsbGJhY2soJ2d5cGhzID4gNjU1MzUgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgaWYgKHRoaXMubG9hZGluZ1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMubG9hZGluZ1tmb250c3RhY2tdID0ge307XG4gICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbZm9udHN0YWNrXTtcblxuICAgIGlmIChsb2FkaW5nW3JhbmdlXSkge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXSA9IFtjYWxsYmFja107XG5cbiAgICAgICAgdmFyIHJhbmdlTmFtZSA9IChyYW5nZSAqIDI1NikgKyAnLScgKyAocmFuZ2UgKiAyNTYgKyAyNTUpO1xuICAgICAgICB2YXIgdXJsID0gZ2x5cGhVcmwoZm9udHN0YWNrLCByYW5nZU5hbWUsIHRoaXMudXJsKTtcblxuICAgICAgICBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgdmFyIGdseXBocyA9ICFlcnIgJiYgbmV3IEdseXBocyhuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1tyYW5nZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2FkaW5nW3JhbmdlXVtpXShlcnIsIHJhbmdlLCBnbHlwaHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGxvYWRpbmdbcmFuZ2VdO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFVzZSBDTkFNRSBzaGFyZGluZyB0byBsb2FkIGEgc3BlY2lmaWMgZ2x5cGggcmFuZ2Ugb3ZlciBhIHJhbmRvbWl6ZWRcbiAqIGJ1dCBjb25zaXN0ZW50IHN1YmRvbWFpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250c3RhY2sgY29tbWEtam9pbmVkIGZvbnRzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmFuZ2UgY29tbWEtam9pbmVkIHJhbmdlXG4gKiBAcGFyYW0ge3VybH0gdXJsIHRlbXBsYXRlZCB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3ViZG9tYWlucz1hYmNdIHN1YmRvbWFpbnMgYXMgYSBzdHJpbmcgd2hlcmUgZWFjaCBsZXR0ZXIgaXMgb25lLlxuICogQHJldHVybnMge3N0cmluZ30gYSB1cmwgdG8gbG9hZCB0aGF0IHNlY3Rpb24gb2YgZ2x5cGhzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBnbHlwaFVybChmb250c3RhY2ssIHJhbmdlLCB1cmwsIHN1YmRvbWFpbnMpIHtcbiAgICBzdWJkb21haW5zID0gc3ViZG9tYWlucyB8fCAnYWJjJztcblxuICAgIHJldHVybiB1cmxcbiAgICAgICAgLnJlcGxhY2UoJ3tzfScsIHN1YmRvbWFpbnNbZm9udHN0YWNrLmxlbmd0aCAlIHN1YmRvbWFpbnMubGVuZ3RoXSlcbiAgICAgICAgLnJlcGxhY2UoJ3tmb250c3RhY2t9JywgZm9udHN0YWNrKVxuICAgICAgICAucmVwbGFjZSgne3JhbmdlfScsIHJhbmdlKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmVhdHVyZXMsIHRleHRGZWF0dXJlcywgZ2VvbWV0cmllcykge1xuXG4gICAgdmFyIGxlZnRJbmRleCA9IHt9LFxuICAgICAgICByaWdodEluZGV4ID0ge30sXG4gICAgICAgIG1lcmdlZEZlYXR1cmVzID0gW10sXG4gICAgICAgIG1lcmdlZEdlb20gPSBbXSxcbiAgICAgICAgbWVyZ2VkVGV4dHMgPSBbXSxcbiAgICAgICAgbWVyZ2VkSW5kZXggPSAwLFxuICAgICAgICBrO1xuXG4gICAgZnVuY3Rpb24gYWRkKGspIHtcbiAgICAgICAgbWVyZ2VkRmVhdHVyZXMucHVzaChmZWF0dXJlc1trXSk7XG4gICAgICAgIG1lcmdlZEdlb20ucHVzaChnZW9tZXRyaWVzW2tdKTtcbiAgICAgICAgbWVyZ2VkVGV4dHMucHVzaCh0ZXh0RmVhdHVyZXNba10pO1xuICAgICAgICBtZXJnZWRJbmRleCsrO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKSB7XG4gICAgICAgIHZhciBpID0gcmlnaHRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgZGVsZXRlIHJpZ2h0SW5kZXhbbGVmdEtleV07XG4gICAgICAgIHJpZ2h0SW5kZXhbcmlnaHRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnBvcCgpO1xuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdID0gbWVyZ2VkR2VvbVtpXVswXS5jb25jYXQoZ2VvbVswXSk7XG4gICAgICAgIHJldHVybiBpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbUxlZnQobGVmdEtleSwgcmlnaHRLZXksIGdlb20pIHtcbiAgICAgICAgdmFyIGkgPSBsZWZ0SW5kZXhbcmlnaHRLZXldO1xuICAgICAgICBkZWxldGUgbGVmdEluZGV4W3JpZ2h0S2V5XTtcbiAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnNoaWZ0KCk7XG4gICAgICAgIG1lcmdlZEdlb21baV1bMF0gPSBnZW9tWzBdLmNvbmNhdChtZXJnZWRHZW9tW2ldWzBdKTtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0S2V5KHRleHQsIGdlb20sIG9uUmlnaHQpIHtcbiAgICAgICAgdmFyIHBvaW50ID0gb25SaWdodCA/IGdlb21bMF1bZ2VvbVswXS5sZW5ndGggLSAxXSA6IGdlb21bMF1bMF07XG4gICAgICAgIHJldHVybiB0ZXh0ICsgJzonICsgcG9pbnQueCArICc6JyArIHBvaW50Lnk7XG4gICAgfVxuXG4gICAgZm9yIChrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBnZW9tID0gZ2VvbWV0cmllc1trXSxcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0RmVhdHVyZXNba107XG5cbiAgICAgICAgaWYgKCF0ZXh0KSB7XG4gICAgICAgICAgICBhZGQoayk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsZWZ0S2V5ID0gZ2V0S2V5KHRleHQsIGdlb20pLFxuICAgICAgICAgICAgcmlnaHRLZXkgPSBnZXRLZXkodGV4dCwgZ2VvbSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKChsZWZ0S2V5IGluIHJpZ2h0SW5kZXgpICYmIChyaWdodEtleSBpbiBsZWZ0SW5kZXgpICYmIChyaWdodEluZGV4W2xlZnRLZXldICE9PSBsZWZ0SW5kZXhbcmlnaHRLZXldKSkge1xuICAgICAgICAgICAgLy8gZm91bmQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IGFkamFjZW50IHRvIGJvdGggZW5kcyBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZSBhbGwgdGhyZWVcbiAgICAgICAgICAgIHZhciBqID0gbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG4gICAgICAgICAgICB2YXIgaSA9IG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBtZXJnZWRHZW9tW2pdKTtcblxuICAgICAgICAgICAgZGVsZXRlIGxlZnRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSByaWdodEluZGV4W3JpZ2h0S2V5XTtcblxuICAgICAgICAgICAgcmlnaHRJbmRleFtnZXRLZXkodGV4dCwgbWVyZ2VkR2VvbVtpXSwgdHJ1ZSldID0gaTtcbiAgICAgICAgICAgIG1lcmdlZEdlb21bal0gPSBudWxsO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobGVmdEtleSBpbiByaWdodEluZGV4KSB7XG4gICAgICAgICAgICAvLyBmb3VuZCBtZXJnZWFibGUgbGluZSBhZGphY2VudCB0byB0aGUgc3RhcnQgb2YgdGhlIGN1cnJlbnQgbGluZSwgbWVyZ2VcbiAgICAgICAgICAgIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHJpZ2h0S2V5IGluIGxlZnRJbmRleCkge1xuICAgICAgICAgICAgLy8gZm91bmQgbWVyZ2VhYmxlIGxpbmUgYWRqYWNlbnQgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZVxuICAgICAgICAgICAgbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vIGFkamFjZW50IGxpbmVzLCBhZGQgYXMgYSBuZXcgaXRlbVxuICAgICAgICAgICAgYWRkKGspO1xuICAgICAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gbWVyZ2VkSW5kZXggLSAxO1xuICAgICAgICAgICAgcmlnaHRJbmRleFtyaWdodEtleV0gPSBtZXJnZWRJbmRleCAtIDE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmZWF0dXJlczogbWVyZ2VkRmVhdHVyZXMsXG4gICAgICAgIHRleHRGZWF0dXJlczogbWVyZ2VkVGV4dHMsXG4gICAgICAgIGdlb21ldHJpZXM6IG1lcmdlZEdlb21cbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEljb25RdWFkczogZ2V0SWNvblF1YWRzLFxuICAgIGdldEdseXBoUXVhZHM6IGdldEdseXBoUXVhZHNcbn07XG5cbnZhciBtaW5TY2FsZSA9IDAuNTsgLy8gdW5kZXJzY2FsZSBieSAxIHpvb20gbGV2ZWxcblxuZnVuY3Rpb24gU3ltYm9sUXVhZChhbmNob3IsIHRsLCB0ciwgYmwsIGJyLCB0ZXgsIGFuZ2xlLCBtaW5TY2FsZSwgbWF4U2NhbGUpIHtcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcbiAgICB0aGlzLnRsID0gdGw7XG4gICAgdGhpcy50ciA9IHRyO1xuICAgIHRoaXMuYmwgPSBibDtcbiAgICB0aGlzLmJyID0gYnI7XG4gICAgdGhpcy50ZXggPSB0ZXg7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuICAgIHRoaXMubWluU2NhbGUgPSBtaW5TY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG59XG5cbmZ1bmN0aW9uIGdldEljb25RdWFkcyhhbmNob3IsIHNoYXBlZEljb24sIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHJlY3QgPSBzaGFwZWRJY29uLmltYWdlLnJlY3Q7XG5cbiAgICB2YXIgYm9yZGVyID0gMTtcbiAgICB2YXIgbGVmdCA9IHNoYXBlZEljb24ubGVmdCAtIGJvcmRlcjtcbiAgICB2YXIgcmlnaHQgPSBsZWZ0ICsgcmVjdC53O1xuICAgIHZhciB0b3AgPSBzaGFwZWRJY29uLnRvcCAtIGJvcmRlcjtcbiAgICB2YXIgYm90dG9tID0gdG9wICsgcmVjdC5oO1xuICAgIHZhciB0bCA9IG5ldyBQb2ludChsZWZ0LCB0b3ApO1xuICAgIHZhciB0ciA9IG5ldyBQb2ludChyaWdodCwgdG9wKTtcbiAgICB2YXIgYnIgPSBuZXcgUG9pbnQocmlnaHQsIGJvdHRvbSk7XG4gICAgdmFyIGJsID0gbmV3IFBvaW50KGxlZnQsIGJvdHRvbSk7XG5cbiAgICB2YXIgYW5nbGUgPSBsYXlvdXRbJ2ljb24tcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIGlmIChhbG9uZ0xpbmUpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2FuY2hvci5zZWdtZW50XTtcbiAgICAgICAgYW5nbGUgKz0gTWF0aC5hdGFuMihhbmNob3IueSAtIHByZXYueSwgYW5jaG9yLnggLSBwcmV2LngpO1xuICAgIH1cblxuICAgIGlmIChhbmdsZSkge1xuICAgICAgICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpLFxuICAgICAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpLFxuICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgIHRsID0gdGwubWF0TXVsdChtYXRyaXgpO1xuICAgICAgICB0ciA9IHRyLm1hdE11bHQobWF0cml4KTtcbiAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgIGJyID0gYnIubWF0TXVsdChtYXRyaXgpO1xuICAgIH1cblxuICAgIHJldHVybiBbbmV3IFN5bWJvbFF1YWQoYW5jaG9yLCB0bCwgdHIsIGJsLCBiciwgc2hhcGVkSWNvbi5pbWFnZS5yZWN0LCAwLCBtaW5TY2FsZSwgSW5maW5pdHkpXTtcbn1cblxuZnVuY3Rpb24gZ2V0R2x5cGhRdWFkcyhhbmNob3IsIHNoYXBpbmcsIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHRleHRSb3RhdGUgPSBsYXlvdXRbJ3RleHQtcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBrZWVwVXByaWdodCA9IGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXTtcblxuICAgIHZhciBwb3NpdGlvbmVkR2x5cGhzID0gc2hhcGluZy5wb3NpdGlvbmVkR2x5cGhzO1xuICAgIHZhciBxdWFkcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2tdO1xuICAgICAgICB2YXIgZ2x5cGggPSBwb3NpdGlvbmVkR2x5cGguZ2x5cGg7XG4gICAgICAgIHZhciByZWN0ID0gZ2x5cGgucmVjdDtcblxuICAgICAgICBpZiAoIXJlY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjZW50ZXJYID0gKHBvc2l0aW9uZWRHbHlwaC54ICsgZ2x5cGguYWR2YW5jZSAvIDIpICogYm94U2NhbGU7XG5cbiAgICAgICAgdmFyIGdseXBoSW5zdGFuY2VzO1xuICAgICAgICB2YXIgbGFiZWxNaW5TY2FsZSA9IG1pblNjYWxlO1xuICAgICAgICBpZiAoYWxvbmdMaW5lKSB7XG4gICAgICAgICAgICBnbHlwaEluc3RhbmNlcyA9IFtdO1xuICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIDEpO1xuICAgICAgICAgICAgaWYgKGtlZXBVcHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IE1hdGgubWluKGxhYmVsTWluU2NhbGUsIGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIC0xKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdseXBoSW5zdGFuY2VzID0gW3tcbiAgICAgICAgICAgICAgICBhbmNob3I6IGFuY2hvcixcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICAgICAgYW5nbGU6IDAsXG4gICAgICAgICAgICAgICAgbWF4U2NhbGU6IEluZmluaXR5LFxuICAgICAgICAgICAgICAgIG1pblNjYWxlOiBtaW5TY2FsZVxuICAgICAgICAgICAgfV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeDEgPSBwb3NpdGlvbmVkR2x5cGgueCArIGdseXBoLmxlZnQsXG4gICAgICAgICAgICB5MSA9IHBvc2l0aW9uZWRHbHlwaC55IC0gZ2x5cGgudG9wLFxuICAgICAgICAgICAgeDIgPSB4MSArIHJlY3QudyxcbiAgICAgICAgICAgIHkyID0geTEgKyByZWN0LmgsXG5cbiAgICAgICAgICAgIG90bCA9IG5ldyBQb2ludCh4MSwgeTEpLFxuICAgICAgICAgICAgb3RyID0gbmV3IFBvaW50KHgyLCB5MSksXG4gICAgICAgICAgICBvYmwgPSBuZXcgUG9pbnQoeDEsIHkyKSxcbiAgICAgICAgICAgIG9iciA9IG5ldyBQb2ludCh4MiwgeTIpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2x5cGhJbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gZ2x5cGhJbnN0YW5jZXNbaV0sXG4gICAgICAgICAgICAgICAgdGwgPSBvdGwsXG4gICAgICAgICAgICAgICAgdHIgPSBvdHIsXG4gICAgICAgICAgICAgICAgYmwgPSBvYmwsXG4gICAgICAgICAgICAgICAgYnIgPSBvYnIsXG4gICAgICAgICAgICAgICAgYW5nbGUgPSBpbnN0YW5jZS5hbmdsZSArIHRleHRSb3RhdGU7XG5cbiAgICAgICAgICAgIGlmIChhbmdsZSkge1xuICAgICAgICAgICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgICAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgdHIgPSB0ci5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgbGFiZWwgZnJvbSBleHRlbmRpbmcgcGFzdCB0aGUgZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICB2YXIgZ2x5cGhNaW5TY2FsZSA9IE1hdGgubWF4KGluc3RhbmNlLm1pblNjYWxlLCBsYWJlbE1pblNjYWxlKTtcblxuICAgICAgICAgICAgdmFyIGdseXBoQW5nbGUgPSAoYW5jaG9yLmFuZ2xlICsgdGV4dFJvdGF0ZSArIGluc3RhbmNlLm9mZnNldCArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG4gICAgICAgICAgICBxdWFkcy5wdXNoKG5ldyBTeW1ib2xRdWFkKGluc3RhbmNlLmFuY2hvciwgdGwsIHRyLCBibCwgYnIsIHJlY3QsIGdseXBoQW5nbGUsIGdseXBoTWluU2NhbGUsIGluc3RhbmNlLm1heFNjYWxlKSk7XG5cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBxdWFkcztcbn1cblxuZnVuY3Rpb24gZ2V0U2VnbWVudEdseXBocyhnbHlwaHMsIGFuY2hvciwgb2Zmc2V0LCBsaW5lLCBzZWdtZW50LCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgdXBzaWRlRG93biA9IGRpcmVjdGlvbiA8IDA7XG5cbiAgICBpZiAob2Zmc2V0IDwgMCkgZGlyZWN0aW9uICo9IC0xO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHNlZ21lbnQrKztcblxuICAgIHZhciBuZXdBbmNob3IgPSBhbmNob3I7XG4gICAgdmFyIGVuZCA9IGxpbmVbc2VnbWVudF07XG4gICAgdmFyIHByZXZTY2FsZSA9IEluZmluaXR5O1xuXG4gICAgb2Zmc2V0ID0gTWF0aC5hYnMob2Zmc2V0KTtcblxuICAgIHZhciBwbGFjZW1lbnRTY2FsZSA9IG1pblNjYWxlO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgdmFyIGRpc3RhbmNlID0gbmV3QW5jaG9yLmRpc3QoZW5kKTtcbiAgICAgICAgdmFyIHNjYWxlID0gb2Zmc2V0IC8gZGlzdGFuY2U7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBhbmdsZSBvZiB0aGUgbGluZSBzZWdtZW50XG4gICAgICAgIHZhciBhbmdsZSA9IE1hdGguYXRhbjIoZW5kLnkgLSBuZXdBbmNob3IueSwgZW5kLnggLSBuZXdBbmNob3IueCk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPCAwKSBhbmdsZSArPSBNYXRoLlBJO1xuICAgICAgICBpZiAodXBzaWRlRG93bikgYW5nbGUgKz0gTWF0aC5QSTtcblxuICAgICAgICBnbHlwaHMucHVzaCh7XG4gICAgICAgICAgICBhbmNob3I6IG5ldyBBbmNob3IobmV3QW5jaG9yLngsIG5ld0FuY2hvci55LCBhbmNob3IuYW5nbGUpLFxuICAgICAgICAgICAgb2Zmc2V0OiB1cHNpZGVEb3duID8gTWF0aC5QSSA6IDAsXG4gICAgICAgICAgICBtaW5TY2FsZTogc2NhbGUsXG4gICAgICAgICAgICBtYXhTY2FsZTogcHJldlNjYWxlLFxuICAgICAgICAgICAgYW5nbGU6IChhbmdsZSArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHNjYWxlIDw9IHBsYWNlbWVudFNjYWxlKSBicmVhaztcblxuICAgICAgICBuZXdBbmNob3IgPSBlbmQ7XG5cbiAgICAgICAgLy8gc2tpcCBkdXBsaWNhdGUgbm9kZXNcbiAgICAgICAgd2hpbGUgKG5ld0FuY2hvci5lcXVhbHMoZW5kKSkge1xuICAgICAgICAgICAgc2VnbWVudCArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICBlbmQgPSBsaW5lW3NlZ21lbnRdO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdW5pdCA9IGVuZC5zdWIobmV3QW5jaG9yKS5fdW5pdCgpO1xuICAgICAgICBuZXdBbmNob3IgPSBuZXdBbmNob3Iuc3ViKHVuaXQuX211bHQoZGlzdGFuY2UpKTtcblxuICAgICAgICBwcmV2U2NhbGUgPSBzY2FsZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2VtZW50U2NhbGU7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVJY29ucztcblxuLy8gRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGljb25zIG5lZWQgdG8gYmUgbG9hZGVkLlxuZnVuY3Rpb24gcmVzb2x2ZUljb25zKGZlYXR1cmVzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdmFyIGljb25zID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWydpY29uLWltYWdlJ10pO1xuICAgICAgICBpZiAoIXRleHQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChpY29ucy5pbmRleE9mKHRleHQpIDwgMCkge1xuICAgICAgICAgICAgaWNvbnMucHVzaCh0ZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpY29ucztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVzb2x2ZVRleHQ7XG5cbi8qKlxuICogRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGdseXBoIHJhbmdlcyBuZWVkIHRvIGJlIGxvYWRlZFxuICogYW5kIGFwcGx5IGFueSB0ZXh0IHByZXByb2Nlc3NpbmcuIFRoZSByZW1haW5pbmcgdXNlcnMgb2YgdGV4dCBzaG91bGRcbiAqIHVzZSB0aGUgYHRleHRGZWF0dXJlc2Aga2V5IHJldHVybmVkIGJ5IHRoaXMgZnVuY3Rpb24gcmF0aGVyIHRoYW4gYWNjZXNzaW5nXG4gKiBmZWF0dXJlIHRleHQgZGlyZWN0bHkuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZXNvbHZlVGV4dChmZWF0dXJlcywgbGF5b3V0UHJvcGVydGllcywgZ2x5cGhzKSB7XG4gICAgdmFyIHRleHRGZWF0dXJlcyA9IFtdO1xuICAgIHZhciBjb2RlcG9pbnRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZpZWxkJ10pO1xuICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgIHRleHRGZWF0dXJlc1tpXSA9IG51bGw7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0ID0gdGV4dC50b1N0cmluZygpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LXRyYW5zZm9ybSddO1xuICAgICAgICBpZiAodHJhbnNmb3JtID09PSAndXBwZXJjYXNlJykge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQudG9Mb2NhbGVVcHBlckNhc2UoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2Zvcm0gPT09ICdsb3dlcmNhc2UnKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpsID0gdGV4dC5sZW5ndGg7IGogPCBqbDsgaisrKSB7XG4gICAgICAgICAgICBjb2RlcG9pbnRzLnB1c2godGV4dC5jaGFyQ29kZUF0KGopKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIGluZGV4ZXMgb2YgZmVhdHVyZXMgd2l0aCB0ZXh0LlxuICAgICAgICB0ZXh0RmVhdHVyZXNbaV0gPSB0ZXh0O1xuICAgIH1cblxuICAgIC8vIGdldCBhIGxpc3Qgb2YgdW5pcXVlIGNvZGVwb2ludHMgd2UgYXJlIG1pc3NpbmdcbiAgICBjb2RlcG9pbnRzID0gdW5pcShjb2RlcG9pbnRzLCBnbHlwaHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dEZlYXR1cmVzOiB0ZXh0RmVhdHVyZXMsXG4gICAgICAgIGNvZGVwb2ludHM6IGNvZGVwb2ludHNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB1bmlxKGlkcywgYWxyZWFkeUhhdmUpIHtcbiAgICB2YXIgdSA9IFtdO1xuICAgIHZhciBsYXN0O1xuICAgIGlkcy5zb3J0KHNvcnROdW1iZXJzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaWRzW2ldICE9PSBsYXN0KSB7XG4gICAgICAgICAgICBsYXN0ID0gaWRzW2ldO1xuICAgICAgICAgICAgaWYgKCFhbHJlYWR5SGF2ZVtsYXN0XSkgdS5wdXNoKGlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHU7XG59XG5cbmZ1bmN0aW9uIHNvcnROdW1iZXJzKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNoYXBlVGV4dDogc2hhcGVUZXh0LFxuICAgIHNoYXBlSWNvbjogc2hhcGVJY29uXG59O1xuXG5cbi8vIFRoZSBwb3NpdGlvbiBvZiBhIGdseXBoIHJlbGF0aXZlIHRvIHRoZSB0ZXh0J3MgYW5jaG9yIHBvaW50LlxuZnVuY3Rpb24gUG9zaXRpb25lZEdseXBoKGNvZGVQb2ludCwgeCwgeSwgZ2x5cGgpIHtcbiAgICB0aGlzLmNvZGVQb2ludCA9IGNvZGVQb2ludDtcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG4gICAgdGhpcy5nbHlwaCA9IGdseXBoO1xufVxuXG4vLyBBIGNvbGxlY3Rpb24gb2YgcG9zaXRpb25lZCBnbHlwaHMgYW5kIHNvbWUgbWV0YWRhdGFcbmZ1bmN0aW9uIFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5wb3NpdGlvbmVkR2x5cGhzID0gcG9zaXRpb25lZEdseXBocztcbiAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICB0aGlzLmJvdHRvbSA9IGJvdHRvbTtcbiAgICB0aGlzLmxlZnQgPSBsZWZ0O1xuICAgIHRoaXMucmlnaHQgPSByaWdodDtcbn1cblxuZnVuY3Rpb24gc2hhcGVUZXh0KHRleHQsIGdseXBocywgbWF4V2lkdGgsIGxpbmVIZWlnaHQsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSwgc3BhY2luZywgdHJhbnNsYXRlKSB7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IFtdO1xuICAgIHZhciBzaGFwaW5nID0gbmV3IFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdHJhbnNsYXRlWzFdLCB0cmFuc2xhdGVbMV0sIHRyYW5zbGF0ZVswXSwgdHJhbnNsYXRlWzBdKTtcblxuICAgIC8vIHRoZSB5IG9mZnNldCAqc2hvdWxkKiBiZSBwYXJ0IG9mIHRoZSBmb250IG1ldGFkYXRhXG4gICAgdmFyIHlPZmZzZXQgPSAtMTc7XG5cbiAgICB2YXIgeCA9IHRyYW5zbGF0ZVswXTtcbiAgICB2YXIgeSA9IHRyYW5zbGF0ZVsxXSArIHlPZmZzZXQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNvZGVQb2ludCA9IHRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgdmFyIGdseXBoID0gZ2x5cGhzW2NvZGVQb2ludF07XG5cbiAgICAgICAgaWYgKCFnbHlwaCkgY29udGludWU7XG5cbiAgICAgICAgcG9zaXRpb25lZEdseXBocy5wdXNoKG5ldyBQb3NpdGlvbmVkR2x5cGgoY29kZVBvaW50LCB4LCB5LCBnbHlwaCkpO1xuICAgICAgICB4ICs9IGdseXBoLmFkdmFuY2UgKyBzcGFjaW5nO1xuICAgIH1cblxuICAgIGlmICghcG9zaXRpb25lZEdseXBocy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSk7XG5cbiAgICByZXR1cm4gc2hhcGluZztcbn1cblxudmFyIGJyZWFrYWJsZSA9IHsgMzI6IHRydWUgfTsgLy8gQ3VycmVudGx5IG9ubHkgYnJlYWtzIGF0IHJlZ3VsYXIgc3BhY2VzXG5cbmZ1bmN0aW9uIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSkge1xuICAgIHZhciBsYXN0U2FmZUJyZWFrID0gbnVsbDtcblxuICAgIHZhciBsZW5ndGhCZWZvcmVDdXJyZW50TGluZSA9IDA7XG4gICAgdmFyIGxpbmVTdGFydEluZGV4ID0gMDtcbiAgICB2YXIgbGluZSA9IDA7XG5cbiAgICB2YXIgbWF4TGluZUxlbmd0aCA9IDA7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IHNoYXBpbmcucG9zaXRpb25lZEdseXBocztcblxuICAgIGlmIChtYXhXaWR0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9uZWRHbHlwaHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2ldO1xuXG4gICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGgueCAtPSBsZW5ndGhCZWZvcmVDdXJyZW50TGluZTtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRHbHlwaC55ICs9IGxpbmVIZWlnaHQgKiBsaW5lO1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb25lZEdseXBoLnggPiBtYXhXaWR0aCAmJiBsYXN0U2FmZUJyZWFrICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGluZUxlbmd0aCA9IHBvc2l0aW9uZWRHbHlwaHNbbGFzdFNhZmVCcmVhayArIDFdLng7XG4gICAgICAgICAgICAgICAgbWF4TGluZUxlbmd0aCA9IE1hdGgubWF4KGxpbmVMZW5ndGgsIG1heExpbmVMZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IGxhc3RTYWZlQnJlYWsgKyAxOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGhzW2tdLnkgKz0gbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25lZEdseXBoc1trXS54IC09IGxpbmVMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGp1c3RpZnkpIHtcbiAgICAgICAgICAgICAgICAgICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgbGFzdFNhZmVCcmVhayAtIDEsIGp1c3RpZnkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxpbmVTdGFydEluZGV4ID0gbGFzdFNhZmVCcmVhayArIDE7XG4gICAgICAgICAgICAgICAgbGFzdFNhZmVCcmVhayA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGVuZ3RoQmVmb3JlQ3VycmVudExpbmUgKz0gbGluZUxlbmd0aDtcbiAgICAgICAgICAgICAgICBsaW5lKys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChicmVha2FibGVbcG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0pIHtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYXN0UG9zaXRpb25lZEdseXBoID0gcG9zaXRpb25lZEdseXBoc1twb3NpdGlvbmVkR2x5cGhzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBsYXN0TGluZUxlbmd0aCA9IGxhc3RQb3NpdGlvbmVkR2x5cGgueCArIGdseXBoc1tsYXN0UG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0uYWR2YW5jZTtcbiAgICBtYXhMaW5lTGVuZ3RoID0gTWF0aC5tYXgobWF4TGluZUxlbmd0aCwgbGFzdExpbmVMZW5ndGgpO1xuXG4gICAgdmFyIGhlaWdodCA9IChsaW5lICsgMSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgcG9zaXRpb25lZEdseXBocy5sZW5ndGggLSAxLCBqdXN0aWZ5KTtcbiAgICBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBib3VuZGluZyBib3hcbiAgICBzaGFwaW5nLnRvcCArPSAtdmVydGljYWxBbGlnbiAqIGhlaWdodDtcbiAgICBzaGFwaW5nLmJvdHRvbSA9IHNoYXBpbmcudG9wICsgaGVpZ2h0O1xuICAgIHNoYXBpbmcubGVmdCArPSAtaG9yaXpvbnRhbEFsaWduICogbWF4TGluZUxlbmd0aDtcbiAgICBzaGFwaW5nLnJpZ2h0ID0gc2hhcGluZy5sZWZ0ICsgbWF4TGluZUxlbmd0aDtcbn1cblxuZnVuY3Rpb24ganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBzdGFydCwgZW5kLCBqdXN0aWZ5KSB7XG4gICAgdmFyIGxhc3RBZHZhbmNlID0gZ2x5cGhzW3Bvc2l0aW9uZWRHbHlwaHNbZW5kXS5jb2RlUG9pbnRdLmFkdmFuY2U7XG4gICAgdmFyIGxpbmVJbmRlbnQgPSAocG9zaXRpb25lZEdseXBoc1tlbmRdLnggKyBsYXN0QWR2YW5jZSkgKiBqdXN0aWZ5O1xuXG4gICAgZm9yICh2YXIgaiA9IHN0YXJ0OyBqIDw9IGVuZDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCAtPSBsaW5lSW5kZW50O1xuICAgIH1cblxufVxuXG5mdW5jdGlvbiBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpIHtcbiAgICB2YXIgc2hpZnRYID0gKGp1c3RpZnkgLSBob3Jpem9udGFsQWxpZ24pICogbWF4TGluZUxlbmd0aDtcbiAgICB2YXIgc2hpZnRZID0gKC12ZXJ0aWNhbEFsaWduICogKGxpbmUgKyAxKSArIDAuNSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCArPSBzaGlmdFg7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueSArPSBzaGlmdFk7XG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIHNoYXBlSWNvbihpbWFnZSwgbGF5b3V0KSB7XG4gICAgaWYgKCFpbWFnZSB8fCAhaW1hZ2UucmVjdCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZHggPSBsYXlvdXRbJ2ljb24tb2Zmc2V0J11bMF07XG4gICAgdmFyIGR5ID0gbGF5b3V0WydpY29uLW9mZnNldCddWzFdO1xuICAgIHZhciB4MSA9IGR4IC0gaW1hZ2Uud2lkdGggLyAyO1xuICAgIHZhciB4MiA9IHgxICsgaW1hZ2Uud2lkdGg7XG4gICAgdmFyIHkxID0gZHkgLSBpbWFnZS5oZWlnaHQgLyAyO1xuICAgIHZhciB5MiA9IHkxICsgaW1hZ2UuaGVpZ2h0O1xuXG4gICAgcmV0dXJuIG5ldyBQb3NpdGlvbmVkSWNvbihpbWFnZSwgeTEsIHkyLCB4MSwgeDIpO1xufVxuXG5mdW5jdGlvbiBQb3NpdGlvbmVkSWNvbihpbWFnZSwgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgIHRoaXMudG9wID0gdG9wO1xuICAgIHRoaXMuYm90dG9tID0gYm90dG9tO1xuICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmluUGFjayA9IHJlcXVpcmUoJy4vYmluX3BhY2snKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTcHJpdGVBdGxhcztcbmZ1bmN0aW9uIFNwcml0ZUF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW1hZ2VzID0ge307XG4gICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0dXJlID0gMDsgLy8gV2ViR0wgSURcbiAgICB0aGlzLmZpbHRlciA9IDA7IC8vIFdlYkdMIElEXG4gICAgdGhpcy5waXhlbFJhdGlvID0gMTtcbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcbn1cblxuU3ByaXRlQXRsYXMucHJvdG90eXBlID0ge1xuICAgIGdldCBkZWJ1ZygpIHtcbiAgICAgICAgcmV0dXJuICdjYW52YXMnIGluIHRoaXM7XG4gICAgfSxcbiAgICBzZXQgZGVidWcodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKG5ld1JhdGlvKSB7XG4gICAgaWYgKHRoaXMucGl4ZWxSYXRpbyA9PT0gbmV3UmF0aW8pIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBvbGRSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbztcbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBuZXdSYXRpbztcblxuICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGggKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLmRhdGE7XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIG9sZFdpZHRoID0gdGhpcy53aWR0aCAqIG9sZFJhdGlvO1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBvbGRSYXRpbztcbiAgICAgICAgdmFyIG5ld1dpZHRoID0gdGhpcy53aWR0aCAqIG5ld1JhdGlvO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBuZXdSYXRpbztcblxuICAgICAgICAvLyBCYXNpYyBpbWFnZSBzY2FsaW5nLiBUT0RPOiBSZXBsYWNlIHRoaXMgd2l0aCBiZXR0ZXIgaW1hZ2Ugc2NhbGluZy5cbiAgICAgICAgdmFyIG5ld0ltYWdlID0gdGhpcy5kYXRhO1xuICAgICAgICB2YXIgb2xkSW1hZ2UgPSBvbGREYXRhO1xuXG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgbmV3SGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgIHZhciBvbGRZT2Zmc2V0ID0gTWF0aC5mbG9vcigoeSAqIG9sZEhlaWdodCkgLyBuZXdIZWlnaHQpICogb2xkV2lkdGg7XG4gICAgICAgICAgICB2YXIgbmV3WU9mZnNldCA9IHkgKiBuZXdXaWR0aDtcbiAgICAgICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgbmV3V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIHZhciBvbGRYID0gTWF0aC5mbG9vcigoeCAqIG9sZFdpZHRoKSAvIG5ld1dpZHRoKTtcbiAgICAgICAgICAgICAgICBuZXdJbWFnZVtuZXdZT2Zmc2V0ICsgeF0gPSBvbGRJbWFnZVtvbGRZT2Zmc2V0ICsgb2xkWF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvbGREYXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXJ0eSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGlydHk7XG59O1xuXG5mdW5jdGlvbiBjb3B5Qml0bWFwKHNyYywgc3JjU3RyaWRlLCBzcmNYLCBzcmNZLCBkc3QsIGRzdFN0cmlkZSwgZHN0WCwgZHN0WSwgd2lkdGgsIGhlaWdodCwgd3JhcCkge1xuICAgIHZhciBzcmNJID0gc3JjWSAqIHNyY1N0cmlkZSArIHNyY1g7XG4gICAgdmFyIGRzdEkgPSBkc3RZICogZHN0U3RyaWRlICsgZHN0WDtcbiAgICB2YXIgeCwgeTtcblxuICAgIGlmICh3cmFwKSB7XG4gICAgICAgIC8vIGFkZCAxIHBpeGVsIHdyYXBwZWQgcGFkZGluZyBvbiBlYWNoIHNpZGUgb2YgdGhlIGltYWdlXG4gICAgICAgIGRzdEkgLT0gZHN0U3RyaWRlO1xuICAgICAgICBmb3IgKHkgPSAtMTsgeSA8PSBoZWlnaHQ7IHkrKywgc3JjSSA9ICgoeSArIGhlaWdodCkgJSBoZWlnaHQgKyBzcmNZKSAqIHNyY1N0cmlkZSArIHNyY1gsIGRzdEkgKz0gZHN0U3RyaWRlKSB7XG4gICAgICAgICAgICBmb3IgKHggPSAtMTsgeCA8PSB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgKCh4ICsgd2lkdGgpICUgd2lkdGgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrLCBzcmNJICs9IHNyY1N0cmlkZSwgZHN0SSArPSBkc3RTdHJpZGUpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgeF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZUltYWdlID0gZnVuY3Rpb24ocGl4ZWxXaWR0aCwgcGl4ZWxIZWlnaHQpIHtcblxuICAgIC8vIEluY3JlYXNlIHRvIG5leHQgbnVtYmVyIGRpdmlzaWJsZSBieSA0LCBidXQgYXQgbGVhc3QgMS5cbiAgICAvLyBUaGlzIGlzIHNvIHdlIGNhbiBzY2FsZSBkb3duIHRoZSB0ZXh0dXJlIGNvb3JkaW5hdGVzIGFuZCBwYWNrIHRoZW1cbiAgICAvLyBpbnRvIDIgYnl0ZXMgcmF0aGVyIHRoYW4gNCBieXRlcy5cbiAgICAvLyBQYWQgaWNvbnMgdG8gcHJldmVudCB0aGVtIGZyb20gcG9sbHV0aW5nIG5laWdoYm91cnMgZHVyaW5nIGxpbmVhciBpbnRlcnBvbGF0aW9uXG4gICAgdmFyIHBhZGRpbmcgPSAyO1xuICAgIHZhciBwYWNrV2lkdGggPSBwaXhlbFdpZHRoICsgcGFkZGluZyArICg0IC0gKHBpeGVsV2lkdGggKyBwYWRkaW5nKSAlIDQpO1xuICAgIHZhciBwYWNrSGVpZ2h0ID0gcGl4ZWxIZWlnaHQgKyBwYWRkaW5nICsgKDQgLSAocGl4ZWxIZWlnaHQgKyBwYWRkaW5nKSAlIDQpOy8vICsgNDtcblxuICAgIC8vIFdlIGhhdmUgdG8gYWxsb2NhdGUgYSBuZXcgYXJlYSBpbiB0aGUgYmluLCBhbmQgc3RvcmUgYW4gZW1wdHkgaW1hZ2UgaW4gaXQuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHJlY3QgPSB0aGlzLmJpbi5hbGxvY2F0ZShwYWNrV2lkdGgsIHBhY2tIZWlnaHQpO1xuICAgIGlmIChyZWN0LncgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgfVxuXG4gICAgcmVjdC5vcmlnaW5hbFdpZHRoID0gcGl4ZWxXaWR0aDtcbiAgICByZWN0Lm9yaWdpbmFsSGVpZ2h0ID0gcGl4ZWxIZWlnaHQ7XG5cbiAgICByZXR1cm4gcmVjdDtcbn07XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uKG5hbWUsIHdyYXApIHtcbiAgICBpZiAodGhpcy5pbWFnZXNbbmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzW25hbWVdO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5zcHJpdGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHRoaXMuc3ByaXRlLmdldFNwcml0ZVBvc2l0aW9uKG5hbWUpO1xuICAgIGlmICghcG9zLndpZHRoIHx8ICFwb3MuaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciB3aWR0aCA9IHBvcy53aWR0aCAvIHBvcy5waXhlbFJhdGlvO1xuICAgIHZhciBoZWlnaHQgPSBwb3MuaGVpZ2h0IC8gcG9zLnBpeGVsUmF0aW87XG4gICAgdmFyIHJlY3QgPSB0aGlzLmFsbG9jYXRlSW1hZ2Uod2lkdGgsIGhlaWdodCk7XG4gICAgaWYgKHJlY3QudyA9PT0gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBuZXcgQXRsYXNJbWFnZShyZWN0LCB3aWR0aCwgaGVpZ2h0LCBwb3Muc2RmKTtcbiAgICB0aGlzLmltYWdlc1tuYW1lXSA9IGltYWdlO1xuXG4gICAgdGhpcy5jb3B5KHJlY3QsIHBvcywgd3JhcCk7XG5cbiAgICByZXR1cm4gaW1hZ2U7XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKG5hbWUsIHJlcGVhdGluZykge1xuICAgIHZhciBpbWFnZSA9IHRoaXMuZ2V0SW1hZ2UobmFtZSwgcmVwZWF0aW5nKTtcbiAgICB2YXIgcmVjdCA9IGltYWdlICYmIGltYWdlLnJlY3Q7XG5cbiAgICBpZiAoIXJlY3QpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB0aGUgaW1hZ2UgaXMgcmVwZWF0aW5nLCBnZXQgdGhlIGNvcnJlY3QgcG9zaXRpb24gb2YgdGhlIGltYWdlLCByYXRoZXIgdGhhbiB0aGVcbiAgICAvLyBvbmUgcm91bmRlZCB1cCB0byA0IHBpeGVscy5cbiAgICB2YXIgd2lkdGggPSByZXBlYXRpbmcgPyBpbWFnZS53aWR0aCA6IHJlY3QudztcbiAgICB2YXIgaGVpZ2h0ID0gcmVwZWF0aW5nID8gaW1hZ2UuaGVpZ2h0IDogcmVjdC5oO1xuICAgIHZhciBwYWRkaW5nID0gMTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNpemU6IFt3aWR0aCwgaGVpZ2h0XSxcbiAgICAgICAgdGw6IFsocmVjdC54ICsgcGFkZGluZykgICAgICAgICAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nKSAgICAgICAgICAvIHRoaXMuaGVpZ2h0XSxcbiAgICAgICAgYnI6IFsocmVjdC54ICsgcGFkZGluZyArIHdpZHRoKSAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nICsgaGVpZ2h0KSAvIHRoaXMuaGVpZ2h0XVxuICAgIH07XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5kYXRhKSB7XG4gICAgICAgIHZhciB3ID0gTWF0aC5mbG9vcih0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdmFyIGggPSBNYXRoLmZsb29yKHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQzMkFycmF5KHcgKiBoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24oZHN0LCBzcmMsIHdyYXApIHtcbiAgICAvLyBpZiAoIXNwcml0ZS0+cmFzdGVyKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnNwcml0ZS5pbWcuZGF0YSkgcmV0dXJuO1xuICAgIHZhciBzcmNJbWcgPSBuZXcgVWludDMyQXJyYXkodGhpcy5zcHJpdGUuaW1nLmRhdGEuYnVmZmVyKTtcblxuICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICB2YXIgZHN0SW1nID0gdGhpcy5kYXRhO1xuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuXG4gICAgY29weUJpdG1hcChcbiAgICAgICAgLyogc291cmNlIGJ1ZmZlciAqLyAgc3JjSW1nLFxuICAgICAgICAvKiBzb3VyY2Ugc3RyaWRlICovICB0aGlzLnNwcml0ZS5pbWcud2lkdGgsXG4gICAgICAgIC8qIHNvdXJjZSB4ICovICAgICAgIHNyYy54LFxuICAgICAgICAvKiBzb3VyY2UgeSAqLyAgICAgICBzcmMueSxcbiAgICAgICAgLyogZGVzdCBidWZmZXIgKi8gICAgZHN0SW1nLFxuICAgICAgICAvKiBkZXN0IHN0cmlkZSAqLyAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLFxuICAgICAgICAvKiBkZXN0IHggKi8gICAgICAgICAoZHN0LnggKyBwYWRkaW5nKSAqIHRoaXMucGl4ZWxSYXRpbyxcbiAgICAgICAgLyogZGVzdCB5ICovICAgICAgICAgKGRzdC55ICsgcGFkZGluZykgKiB0aGlzLnBpeGVsUmF0aW8sXG4gICAgICAgIC8qIGljb24gZGltZW5zaW9uICovIHNyYy53aWR0aCxcbiAgICAgICAgLyogaWNvbiBkaW1lbnNpb24gKi8gc3JjLmhlaWdodCxcbiAgICAgICAgLyogd3JhcCAqLyB3cmFwXG4gICAgKTtcblxuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLmFkZEljb25zID0gZnVuY3Rpb24oaWNvbnMsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpY29ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmdldEltYWdlKGljb25zW2ldKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCB0aGlzLmltYWdlcyk7XG59O1xuXG5TcHJpdGVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsLCBsaW5lYXIpIHtcbiAgICB2YXIgZmlyc3QgPSBmYWxzZTtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZmlyc3QgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgfVxuXG4gICAgdmFyIGZpbHRlclZhbCA9IGxpbmVhciA/IGdsLkxJTkVBUiA6IGdsLk5FQVJFU1Q7XG4gICAgaWYgKGZpbHRlclZhbCAhPT0gdGhpcy5maWx0ZXIpIHtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGZpbHRlclZhbCk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBmaWx0ZXJWYWwpO1xuICAgICAgICB0aGlzLmZpbHRlciA9IGZpbHRlclZhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kaXJ0eSkge1xuICAgICAgICB0aGlzLmFsbG9jYXRlKCk7XG5cbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIGdsLlRFWFRVUkVfMkQsIC8vIGVudW0gdGFyZ2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW5kIGxldmVsXG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gaW5kIGludGVybmFsZm9ybWF0XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgLy8gR0xzaXplaSB3aWR0aFxuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvLCAvLyBHTHNpemVpIGhlaWdodFxuICAgICAgICAgICAgICAgIDAsIC8vIGluZCBib3JkZXJcbiAgICAgICAgICAgICAgICBnbC5SR0JBLCAvLyBlbnVtIGZvcm1hdFxuICAgICAgICAgICAgICAgIGdsLlVOU0lHTkVEX0JZVEUsIC8vIGVudW0gdHlwZVxuICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KHRoaXMuZGF0YS5idWZmZXIpIC8vIE9iamVjdCBkYXRhXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChcbiAgICAgICAgICAgICAgICBnbC5URVhUVVJFXzJELCAvLyBlbnVtIHRhcmdldFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCBsZXZlbFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCB4b2Zmc2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW50IHlvZmZzZXRcbiAgICAgICAgICAgICAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLCAvLyBsb25nIHdpZHRoXG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8sIC8vIGxvbmcgaGVpZ2h0XG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gZW51bSBmb3JtYXRcbiAgICAgICAgICAgICAgICBnbC5VTlNJR05FRF9CWVRFLCAvLyBlbnVtIHR5cGVcbiAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheSh0aGlzLmRhdGEuYnVmZmVyKSAvLyBPYmplY3QgcGl4ZWxzXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuXG4gICAgICAgIC8vIERFQlVHXG4gICAgICAgIGlmICh0aGlzLmN0eCkge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmN0eC5nZXRJbWFnZURhdGEoMCwgMCwgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8pO1xuICAgICAgICAgICAgZGF0YS5kYXRhLnNldChuZXcgVWludDhDbGFtcGVkQXJyYXkodGhpcy5kYXRhLmJ1ZmZlcikpO1xuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54ICogdGhpcy5waXhlbFJhdGlvLCBmcmVlLnkgKiB0aGlzLnBpeGVsUmF0aW8sIGZyZWUudyAqIHRoaXMucGl4ZWxSYXRpbywgZnJlZS5oICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBBdGxhc0ltYWdlKHJlY3QsIHdpZHRoLCBoZWlnaHQsIHNkZikge1xuICAgIHRoaXMucmVjdCA9IHJlY3Q7XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuc2RmID0gc2RmO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBMYXRMbmcgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZycpO1xudmFyIExhdExuZ0JvdW5kcyA9IHJlcXVpcmUoJy4uL2dlby9sYXRfbG5nX2JvdW5kcycpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYW1lcmFPcHRpb25zXG4gKiBAcHJvcGVydHkge0FycmF5fSBbY2VudGVyXSBMYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIChwYXNzZWQgYXMgYFtsYXQsIGxuZ11gKVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6b29tXSBNYXAgem9vbSBsZXZlbFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtiZWFyaW5nXSBNYXAgcm90YXRpb24gYmVhcmluZyBpbiBkZWdyZWVzIGNvdW50ZXItY2xvY2t3aXNlIGZyb20gbm9ydGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcGl0Y2hdIFRoZSBhbmdsZSBhdCB3aGljaCB0aGUgY2FtZXJhIGlzIGxvb2tpbmcgYXQgdGhlIGdyb3VuZFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gW0FuaW1hdGlvbk9wdGlvbnNdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTUwMF0gTnVtYmVyIGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gW2Vhc2luZ11cbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IFtvZmZzZXQ9WzAsMF1dIHBvaW50LCBvcmlnaW4gb2YgbW92ZW1lbnQgcmVsYXRpdmUgdG8gbWFwIGNlbnRlclxuICogQHByb3BlcnR5IHtib29sZWFufSBbYW5pbWF0ZT10cnVlXSBXaGVuIHNldCB0byBmYWxzZSwgbm8gYW5pbWF0aW9uIGhhcHBlbnNcbiAqL1xuXG52YXIgQ2FtZXJhID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHt9O1xuXG51dGlsLmV4dGVuZChDYW1lcmEucHJvdG90eXBlLCAvKiogQGxlbmRzIE1hcC5wcm90b3R5cGUgKi97XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IHZpZXcgZ2VvZ3JhcGhpY2FsIHBvaW50LlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmNlbnRlcjsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgbG9jYXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjZW50ZXIgTGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSAocGFzc2VkIGFzIGBbbGF0LCBsbmddYClcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5zZXRDZW50ZXIoWy03NCwgMzhdKTtcbiAgICAgKi9cbiAgICBzZXRDZW50ZXI6IGZ1bmN0aW9uKGNlbnRlcikge1xuICAgICAgICB0aGlzLmp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUGFuIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgcGl4ZWxzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvZmZzZXQgW3gsIHldXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHBhbkJ5OiBmdW5jdGlvbihvZmZzZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5wYW5Ubyh0aGlzLnRyYW5zZm9ybS5jZW50ZXIsIHV0aWwuZXh0ZW5kKHtvZmZzZXQ6IFBvaW50LmNvbnZlcnQob2Zmc2V0KS5tdWx0KC0xKX0sIG9wdGlvbnMpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFBhbiB0byBhIGNlcnRhaW4gbG9jYXRpb24gd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBsYXRsbmcgYSBgTGF0TG5nYCBvYmplY3RcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcGFuVG86IGZ1bmN0aW9uKGxhdGxuZywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLnN0b3AoKTtcblxuICAgICAgICBsYXRsbmcgPSBMYXRMbmcuY29udmVydChsYXRsbmcpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2UsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLnJvdGF0ZSgtdHIuYW5nbGUpLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldCk7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSB0ci51bnByb2plY3QoZnJvbS5hZGQodG8uc3ViKGZyb20pLm11bHQoaykpKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgem9vbVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnRyYW5zZm9ybS56b29tOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIG1hcCB6b29tLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3pvb206IHpvb219KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBNYXAgem9vbSBsZXZlbFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gem9vbSB0aGUgbWFwIHRvIDVcbiAgICAgKiBtYXAuc2V0Wm9vbSg1KTtcbiAgICAgKi9cbiAgICBzZXRab29tOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHt6b29tOiB6b29tfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRvIGEgY2VydGFpbiB6b29tIGxldmVsIHdpdGggZWFzaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbVRvOiBmdW5jdGlvbih6b29tLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIG9wdGlvbnMuZWFzaW5nID0gdGhpcy5fdXBkYXRlRWFzaW5nKG9wdGlvbnMuZHVyYXRpb24sIHpvb20sIG9wdGlvbnMuZWFzaW5nKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLmNlbnRlcixcbiAgICAgICAgICAgIHN0YXJ0Wm9vbSA9IHRyLnpvb207XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkgb3B0aW9ucy5kdXJhdGlvbiA9IDA7XG5cbiAgICAgICAgaWYgKCF0aGlzLnpvb21pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRab29tQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0Wm9vbSwgem9vbSwgayksIGFyb3VuZCk7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmUnKS5maXJlKCd6b29tJyk7XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5lYXNlID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmR1cmF0aW9uID49IDIwMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5kdXJhdGlvbiA8IDIwMCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX29uWm9vbUVuZCk7XG4gICAgICAgICAgICB0aGlzLl9vblpvb21FbmQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCAyMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb20gaW4gYnkgMSBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHpvb21JbjogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSArIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIG91dCBieSAxIGxldmVsXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbU91dDogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSAtIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBiZWFyaW5nIGluIGRlZ3JlZXNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldEJlYXJpbmc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0uYmVhcmluZzsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgcm90YXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7YmVhcmluZzogYmVhcmluZ30pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiZWFyaW5nIE1hcCByb3RhdGlvbiBiZWFyaW5nIGluIGRlZ3JlZXMgY291bnRlci1jbG9ja3dpc2UgZnJvbSBub3J0aFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gcm90YXRlIHRoZSBtYXAgdG8gOTAgZGVncmVlc1xuICAgICAqIG1hcC5zZXRCZWFyaW5nKDkwKTtcbiAgICAgKi9cbiAgICBzZXRCZWFyaW5nOiBmdW5jdGlvbihiZWFyaW5nKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHtiZWFyaW5nOiBiZWFyaW5nfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSBiZWFyaW5nIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgZGVncmVlcyB3aXRoIGVhc2luZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGJlYXJpbmdcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcm90YXRlVG86IGZ1bmN0aW9uKGJlYXJpbmcsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBlYXNpbmc6IHV0aWwuZWFzZVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5nZXRCZWFyaW5nKCksXG4gICAgICAgICAgICBhcm91bmQgPSB0ci5jZW50ZXI7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBiZWFyaW5nID0gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhiZWFyaW5nLCBzdGFydCk7XG5cbiAgICAgICAgdGhpcy5yb3RhdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRCZWFyaW5nQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0LCBiZWFyaW5nLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtYXAgYmVhcmluZyB0byAwIChub3J0aCkgd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QW5pbWF0aW9uT3B0aW9uc31cbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICByZXNldE5vcnRoOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvdGF0ZVRvKDAsIHV0aWwuZXh0ZW5kKHtkdXJhdGlvbjogMTAwMH0sIG9wdGlvbnMpKTtcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgYW5nbGUgaW4gZGVncmVlc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0UGl0Y2g6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucGl0Y2g7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgbWFwIGFuZ2xlLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3BpdGNoOiBwaXRjaH0pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXRjaCBUaGUgYW5nbGUgYXQgd2hpY2ggdGhlIGNhbWVyYSBpcyBsb29raW5nIGF0IHRoZSBncm91bmRcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRQaXRjaDogZnVuY3Rpb24ocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8oe3BpdGNoOiBwaXRjaH0pO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIFpvb20gdG8gY29udGFpbiBjZXJ0YWluIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJvdW5kcyBbW21pbkxhdCwgbWluTG5nXSwgW21heExhdCwgbWF4TG5nXV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5zcGVlZD0xLjJdIEhvdyBmYXN0IGFuaW1hdGlvbiBvY2N1cnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuY3VydmU9MS40Ml0gSG93IG11Y2ggem9vbWluZyBvdXQgb2NjdXJzIGR1cmluZyBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmVhc2luZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLnBhZGRpbmcgaG93IG11Y2ggcGFkZGluZyB0aGVyZSBpcyBhcm91bmQgdGhlIGdpdmVuIGJvdW5kcyBvbiBlYWNoIHNpZGUgaW4gcGl4ZWxzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMubWF4Wm9vbVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIGZpdEJvdW5kczogZnVuY3Rpb24oYm91bmRzLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIG1heFpvb206IEluZmluaXR5XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIGJvdW5kcyA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KGJvdW5kcyk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLFxuICAgICAgICAgICAgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG53ID0gdHIucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxuICAgICAgICAgICAgc2UgPSB0ci5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSksXG4gICAgICAgICAgICBzaXplID0gc2Uuc3ViKG53KSxcbiAgICAgICAgICAgIHNjYWxlWCA9ICh0ci53aWR0aCAtIG9wdGlvbnMucGFkZGluZyAqIDIgLSBNYXRoLmFicyhvZmZzZXQueCkgKiAyKSAvIHNpemUueCxcbiAgICAgICAgICAgIHNjYWxlWSA9ICh0ci5oZWlnaHQgLSBvcHRpb25zLnBhZGRpbmcgKiAyIC0gTWF0aC5hYnMob2Zmc2V0LnkpICogMikgLyBzaXplLnk7XG5cbiAgICAgICAgb3B0aW9ucy5jZW50ZXIgPSB0ci51bnByb2plY3QobncuYWRkKHNlKS5kaXYoMikpO1xuICAgICAgICBvcHRpb25zLnpvb20gPSBNYXRoLm1pbih0ci5zY2FsZVpvb20odHIuc2NhbGUgKiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSkpLCBvcHRpb25zLm1heFpvb20pO1xuICAgICAgICBvcHRpb25zLmJlYXJpbmcgPSAwO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zLmxpbmVhciA/XG4gICAgICAgICAgICB0aGlzLmVhc2VUbyhvcHRpb25zKSA6XG4gICAgICAgICAgICB0aGlzLmZseVRvKG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgYW55IGNvbWJpbmF0aW9uIG9mIGNlbnRlciwgem9vbSwgYmVhcmluZywgYW5kIHBpdGNoLCB3aXRob3V0XG4gICAgICogYSB0cmFuc2l0aW9uLiBUaGUgbWFwIHdpbGwgcmV0YWluIHRoZSBjdXJyZW50IHZhbHVlcyBmb3IgYW55IG9wdGlvbnNcbiAgICAgKiBub3QgaW5jbHVkZWQgaW4gYG9wdGlvbnNgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBqdW1wVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICB6b29tQ2hhbmdlZCA9IGZhbHNlLFxuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSBmYWxzZSxcbiAgICAgICAgICAgIHBpdGNoQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICgnY2VudGVyJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3pvb20nIGluIG9wdGlvbnMgJiYgdHIuem9vbSAhPT0gK29wdGlvbnMuem9vbSkge1xuICAgICAgICAgICAgem9vbUNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuem9vbSA9ICtvcHRpb25zLnpvb207XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2JlYXJpbmcnIGluIG9wdGlvbnMgJiYgdHIuYmVhcmluZyAhPT0gK29wdGlvbnMuYmVhcmluZykge1xuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuYmVhcmluZyA9ICtvcHRpb25zLmJlYXJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3BpdGNoJyBpbiBvcHRpb25zICYmIHRyLnBpdGNoICE9PSArb3B0aW9ucy5waXRjaCkge1xuICAgICAgICAgICAgcGl0Y2hDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyLnBpdGNoID0gK29wdGlvbnMucGl0Y2g7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZScpO1xuXG4gICAgICAgIGlmICh6b29tQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5maXJlKCd6b29tJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYmVhcmluZ0NoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGl0Y2hDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3BpdGNoJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEVhc2luZyBhbmltYXRpb24gdG8gYSBzcGVjaWZpZWQgbG9jYXRpb24vem9vbS9iZWFyaW5nXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NhbWVyYU9wdGlvbnMrQW5pbWF0aW9uT3B0aW9uc30gb3B0aW9ucyBtYXAgdmlldyBhbmQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICBlYXNlVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdLFxuICAgICAgICAgICAgZHVyYXRpb246IDUwMCxcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkucm90YXRlKC10ci5hbmdsZSksXG4gICAgICAgICAgICBmcm9tID0gdHIucG9pbnQsXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgc3RhcnRQaXRjaCA9IHRoaXMuZ2V0UGl0Y2goKTtcblxuICAgICAgICB2YXIgem9vbSA9ICd6b29tJyBpbiBvcHRpb25zID8gK29wdGlvbnMuem9vbSA6IHN0YXJ0Wm9vbTtcbiAgICAgICAgdmFyIGJlYXJpbmcgPSAnYmVhcmluZycgaW4gb3B0aW9ucyA/IHRoaXMuX25vcm1hbGl6ZUJlYXJpbmcob3B0aW9ucy5iZWFyaW5nLCBzdGFydEJlYXJpbmcpIDogc3RhcnRCZWFyaW5nO1xuICAgICAgICB2YXIgcGl0Y2ggPSAncGl0Y2gnIGluIG9wdGlvbnMgPyArb3B0aW9ucy5waXRjaCA6IHN0YXJ0UGl0Y2g7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgdG8gPSAnY2VudGVyJyBpbiBvcHRpb25zID8gdHIucHJvamVjdChMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcikpLnN1YihvZmZzZXQuZGl2KHNjYWxlKSkgOiBmcm9tLFxuICAgICAgICAgICAgYXJvdW5kO1xuXG4gICAgICAgIGlmICh6b29tICE9PSBzdGFydFpvb20pIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKHRvLnN1Yihmcm9tKS5kaXYoMSAtIDEgLyBzY2FsZSkpKTtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgaWYgKHpvb20gIT09IHN0YXJ0Wm9vbSkge1xuICAgICAgICAgICAgICAgIHRyLnNldFpvb21Bcm91bmQoaW50ZXJwb2xhdGUoc3RhcnRab29tLCB6b29tLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHIuY2VudGVyID0gdHIudW5wcm9qZWN0KGZyb20uYWRkKHRvLnN1Yihmcm9tKS5tdWx0KGspKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBpdGNoICE9PSBzdGFydFBpdGNoKSB7XG4gICAgICAgICAgICAgICAgdHIucGl0Y2ggPSBpbnRlcnBvbGF0ZShzdGFydFBpdGNoLCBwaXRjaCwgayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICAgICAgaWYgKHRoaXMuem9vbWluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucm90YXRpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGbHlpbmcgYW5pbWF0aW9uIHRvIGEgc3BlY2lmaWVkIGxvY2F0aW9uL3pvb20vYmVhcmluZyB3aXRoIGF1dG9tYXRpYyBjdXJ2ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc3BlZWQ9MS4yXSBIb3cgZmFzdCBhbmltYXRpb24gb2NjdXJzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmN1cnZlPTEuNDJdIEhvdyBtdWNoIHpvb21pbmcgb3V0IG9jY3VycyBkdXJpbmcgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZWFzaW5nXVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gZmx5IHdpdGggZGVmYXVsdCBvcHRpb25zIHRvIG51bGwgaXNsYW5kXG4gICAgICogbWFwLmZseVRvKHtjZW50ZXI6IFswLCAwXSwgem9vbTogOX0pO1xuICAgICAqIC8vIHVzaW5nIGZseVRvIG9wdGlvbnNcbiAgICAgKiBtYXAuZmx5VG8oe1xuICAgICAqICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICogICB6b29tOiA5LFxuICAgICAqICAgc3BlZWQ6IDAuMixcbiAgICAgKiAgIGN1cnZlOiAxLFxuICAgICAqICAgZWFzaW5nOiBmdW5jdGlvbih0KSB7XG4gICAgICogICAgIHJldHVybiB0O1xuICAgICAqICAgfVxuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZseVRvOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIHNwZWVkOiAxLjIsXG4gICAgICAgICAgICBjdXJ2ZTogMS40MixcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpO1xuXG4gICAgICAgIHZhciBjZW50ZXIgPSAnY2VudGVyJyBpbiBvcHRpb25zID8gTGF0TG5nLmNvbnZlcnQob3B0aW9ucy5jZW50ZXIpIDogdGhpcy5nZXRDZW50ZXIoKTtcbiAgICAgICAgdmFyIHpvb20gPSAnem9vbScgaW4gb3B0aW9ucyA/ICArb3B0aW9ucy56b29tIDogc3RhcnRab29tO1xuICAgICAgICB2YXIgYmVhcmluZyA9ICdiZWFyaW5nJyBpbiBvcHRpb25zID8gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhvcHRpb25zLmJlYXJpbmcsIHN0YXJ0QmVhcmluZykgOiBzdGFydEJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGNlbnRlcikuc3ViKG9mZnNldC5kaXYoc2NhbGUpKTtcblxuICAgICAgICB2YXIgc3RhcnRXb3JsZFNpemUgPSB0ci53b3JsZFNpemUsXG4gICAgICAgICAgICByaG8gPSBvcHRpb25zLmN1cnZlLFxuICAgICAgICAgICAgViA9IG9wdGlvbnMuc3BlZWQsXG5cbiAgICAgICAgICAgIHcwID0gTWF0aC5tYXgodHIud2lkdGgsIHRyLmhlaWdodCksXG4gICAgICAgICAgICB3MSA9IHcwIC8gc2NhbGUsXG4gICAgICAgICAgICB1MSA9IHRvLnN1Yihmcm9tKS5tYWcoKSxcbiAgICAgICAgICAgIHJobzIgPSByaG8gKiByaG87XG5cbiAgICAgICAgZnVuY3Rpb24gcihpKSB7XG4gICAgICAgICAgICB2YXIgYiA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIChpID8gLTEgOiAxKSAqIHJobzIgKiByaG8yICogdTEgKiB1MSkgLyAoMiAqIChpID8gdzEgOiB3MCkgKiByaG8yICogdTEpO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubG9nKE1hdGguc3FydChiICogYiArIDEpIC0gYik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaW5oKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSAtIE1hdGguZXhwKC1uKSkgLyAyOyB9XG4gICAgICAgIGZ1bmN0aW9uIGNvc2gobikgeyByZXR1cm4gKE1hdGguZXhwKG4pICsgTWF0aC5leHAoLW4pKSAvIDI7IH1cbiAgICAgICAgZnVuY3Rpb24gdGFuaChuKSB7IHJldHVybiBzaW5oKG4pIC8gY29zaChuKTsgfVxuXG4gICAgICAgIHZhciByMCA9IHIoMCksXG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIChjb3NoKHIwKSAvIGNvc2gocjAgKyByaG8gKiBzKSk7IH0sXG4gICAgICAgICAgICB1ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHcwICogKChjb3NoKHIwKSAqIHRhbmgocjAgKyByaG8gKiBzKSAtIHNpbmgocjApKSAvIHJobzIpIC8gdTE7IH0sXG4gICAgICAgICAgICBTID0gKHIoMSkgLSByMCkgLyByaG87XG5cbiAgICAgICAgaWYgKE1hdGguYWJzKHUxKSA8IDAuMDAwMDAxKSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnModzAgLSB3MSkgPCAwLjAwMDAwMSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBrID0gdzEgPCB3MCA/IC0xIDogMTtcbiAgICAgICAgICAgIFMgPSBNYXRoLmFicyhNYXRoLmxvZyh3MSAvIHcwKSkgLyByaG87XG5cbiAgICAgICAgICAgIHUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gTWF0aC5leHAoayAqIHJobyAqIHMpOyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0aW9ucy5kdXJhdGlvbiA9IDEwMDAgKiBTIC8gVjtcblxuICAgICAgICB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuXG4gICAgICAgIHRoaXMuX2Vhc2UoZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgIHZhciBzID0gayAqIFMsXG4gICAgICAgICAgICAgICAgdXMgPSB1KHMpO1xuXG4gICAgICAgICAgICB0ci56b29tID0gc3RhcnRab29tICsgdHIuc2NhbGVab29tKDEgLyB3KHMpKTtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdCh1cykpLCBzdGFydFdvcmxkU2l6ZSk7XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgaWYgKGJlYXJpbmcgIT09IHN0YXJ0QmVhcmluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy56b29taW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGlzRWFzaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fYWJvcnRGbjtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU3RvcCBjdXJyZW50IGFuaW1hdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9hYm9ydEZuKSB7XG4gICAgICAgICAgICB0aGlzLl9hYm9ydEZuLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fYWJvcnRGbjtcblxuICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9maW5pc2hGbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2Vhc2U6IGZ1bmN0aW9uKGZyYW1lLCBmaW5pc2gsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoRm4gPSBmaW5pc2g7XG4gICAgICAgIHRoaXMuX2Fib3J0Rm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICBmcmFtZS5jYWxsKHRoaXMsIG9wdGlvbnMuZWFzaW5nKHQpKTtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2Fib3J0Rm47XG4gICAgICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5fZmluaXNoRm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgPyAwIDogb3B0aW9ucy5kdXJhdGlvbiwgdGhpcyk7XG4gICAgfSxcblxuICAgIC8vIGNvbnZlcnQgYmVhcmluZyBzbyB0aGF0IGl0J3MgbnVtZXJpY2FsbHkgY2xvc2UgdG8gdGhlIGN1cnJlbnQgb25lIHNvIHRoYXQgaXQgaW50ZXJwb2xhdGVzIHByb3Blcmx5XG4gICAgX25vcm1hbGl6ZUJlYXJpbmc6IGZ1bmN0aW9uKGJlYXJpbmcsIGN1cnJlbnRCZWFyaW5nKSB7XG4gICAgICAgIGJlYXJpbmcgPSB1dGlsLndyYXAoYmVhcmluZywgLTE4MCwgMTgwKTtcbiAgICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhiZWFyaW5nIC0gY3VycmVudEJlYXJpbmcpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyAtIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgLT0gMzYwO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyArIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgKz0gMzYwO1xuICAgICAgICByZXR1cm4gYmVhcmluZztcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUVhc2luZzogZnVuY3Rpb24oZHVyYXRpb24sIHpvb20sIGJlemllcikge1xuICAgICAgICB2YXIgZWFzaW5nO1xuXG4gICAgICAgIGlmICh0aGlzLmVhc2UpIHtcbiAgICAgICAgICAgIHZhciBlYXNlID0gdGhpcy5lYXNlLFxuICAgICAgICAgICAgICAgIHQgPSAoRGF0ZS5ub3coKSAtIGVhc2Uuc3RhcnQpIC8gZWFzZS5kdXJhdGlvbixcbiAgICAgICAgICAgICAgICBzcGVlZCA9IGVhc2UuZWFzaW5nKHQgKyAwLjAxKSAtIGVhc2UuZWFzaW5nKHQpLFxuXG4gICAgICAgICAgICAgICAgLy8gUXVpY2sgaGFjayB0byBtYWtlIG5ldyBiZXppZXIgdGhhdCBpcyBjb250aW51b3VzIHdpdGggbGFzdFxuICAgICAgICAgICAgICAgIHggPSAwLjI3IC8gTWF0aC5zcXJ0KHNwZWVkICogc3BlZWQgKyAwLjAwMDEpICogMC4wMSxcbiAgICAgICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KDAuMjcgKiAwLjI3IC0geCAqIHgpO1xuXG4gICAgICAgICAgICBlYXNpbmcgPSB1dGlsLmJlemllcih4LCB5LCAwLjI1LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyA9IGJlemllciA/IHV0aWwuYmV6aWVyLmFwcGx5KHV0aWwsIGJlemllcikgOiB1dGlsLmVhc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSBpbmZvcm1hdGlvbiBvbiBjdXJyZW50IGVhc2luZ1xuICAgICAgICB0aGlzLmVhc2UgPSB7XG4gICAgICAgICAgICBzdGFydDogKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcbiAgICAgICAgICAgIHRvOiBNYXRoLnBvdygyLCB6b29tKSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgIGVhc2luZzogZWFzaW5nXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGVhc2luZztcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBdHRyaWJ1dGlvbjtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2xcbiAqIEBjbGFzcyBBdHRyaWJ1dGlvblxuICogQGV4YW1wbGVcbiAqIG1hcC5hZGRDb250cm9sKG5ldyBtYXBib3hnbC5BdHRyaWJ1dGlvbigpKTtcbiAqL1xuZnVuY3Rpb24gQXR0cmlidXRpb24oKSB7fVxuXG5BdHRyaWJ1dGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICdib3R0b20tcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsLWF0dHJpYicsXG4gICAgICAgICAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBET00uY3JlYXRlKCdkaXYnLCBjbGFzc05hbWUsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmxvYWQnLCB0aGlzLl91cGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX3VwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgbWFwLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fdXBkYXRlLmJpbmQodGhpcykpO1xuICAgICAgICBtYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVFZGl0TGluay5iaW5kKHRoaXMpKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGF0dHJpYnV0aW9ucyA9IFtdO1xuXG4gICAgICAgIGlmICh0aGlzLl9tYXAuc3R5bGUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzW2lkXTtcbiAgICAgICAgICAgICAgICBpZiAoc291cmNlLmF0dHJpYnV0aW9uICYmIGF0dHJpYnV0aW9ucy5pbmRleE9mKHNvdXJjZS5hdHRyaWJ1dGlvbikgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9ucy5wdXNoKHNvdXJjZS5hdHRyaWJ1dGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY29udGFpbmVyLmlubmVySFRNTCA9IGF0dHJpYnV0aW9ucy5qb2luKCcgfCAnKTtcbiAgICAgICAgdGhpcy5fZWRpdExpbmsgPSB0aGlzLl9jb250YWluZXIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbWFwYm94LWltcHJvdmUtbWFwJylbMF07XG4gICAgICAgIHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVFZGl0TGluazogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9lZGl0TGluaykge1xuICAgICAgICAgICAgdmFyIGNlbnRlciA9IHRoaXMuX21hcC5nZXRDZW50ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX2VkaXRMaW5rLmhyZWYgPSAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXAtZmVlZGJhY2svIy8nICtcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyLmxuZyArICcvJyArIGNlbnRlci5sYXQgKyAnLycgKyBNYXRoLnJvdW5kKHRoaXMuX21hcC5nZXRab29tKCkgKyAxKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbnRyb2w7XG5cbi8qKlxuICogQSBiYXNlIGNsYXNzIGZvciBtYXAtcmVsYXRlZCBpbnRlcmZhY2UgZWxlbWVudHMuXG4gKlxuICogQGNsYXNzIENvbnRyb2xcbiAqL1xuZnVuY3Rpb24gQ29udHJvbCgpIHt9XG5cbkNvbnRyb2wucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIEFkZCB0aGlzIGNvbnRyb2wgdG8gdGhlIG1hcCwgcmV0dXJuaW5nIHRoZSBjb250cm9sIGl0c2VsZlxuICAgICAqIGZvciBjaGFpbmluZy4gVGhpcyB3aWxsIGluc2VydCB0aGUgY29udHJvbCdzIERPTSBlbGVtZW50IGludG9cbiAgICAgKiB0aGUgbWFwJ3MgRE9NIGVsZW1lbnQgaWYgdGhlIGNvbnRyb2wgaGFzIGEgYHBvc2l0aW9uYCBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbWFwXG4gICAgICogQHJldHVybnMge0NvbnRyb2x9IHRoaXNcbiAgICAgKi9cbiAgICBhZGRUbzogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMuX21hcCA9IG1hcDtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMucG9zaXRpb24pIHtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aGlzLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgICAgICB2YXIgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xuICAgICAgICAgICAgY29udGFpbmVyLmNsYXNzTmFtZSArPSAnIG1hcGJveGdsLWN0cmwnO1xuICAgICAgICAgICAgaWYgKHBvcy5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuaW5zZXJ0QmVmb3JlKGNvbnRhaW5lciwgY29ybmVyLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhpcyBjb250cm9sIGZyb20gdGhlIG1hcCBpdCBoYXMgYmVlbiBhZGRlZCB0by5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtDb250cm9sfSB0aGlzXG4gICAgICovXG4gICAgcmVtb3ZlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub25SZW1vdmUpIHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcbiAgICAgICAgdGhpcy5fbWFwID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOYXZpZ2F0aW9uO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuYXZpZ2F0aW9uIGNvbnRyb2wgd2l0aCB6b29tIGJ1dHRvbnMgYW5kIGEgY29tcGFzc1xuICogQGNsYXNzIE5hdmlnYXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wb3NpdGlvbj10b3AtcmlnaHRdIEEgc3RyaW5nIGluZGljYXRpbmcgdGhlIGNvbnRyb2wncyBwb3NpdGlvbiBvbiB0aGUgbWFwLiBPcHRpb25zIGFyZSBgdG9wLXJpZ2h0YCwgYHRvcC1sZWZ0YCwgYGJvdHRvbS1yaWdodGAsIGBib3R0b20tbGVmdGBcbiAqIEBleGFtcGxlXG4gKiBtYXAuYWRkQ29udHJvbChuZXcgbWFwYm94Z2wuTmF2aWdhdGlvbih7cG9zaXRpb246ICd0b3AtbGVmdCd9KSk7IC8vIHBvc2l0aW9uIGlzIG9wdGlvbmFsXG4gKi9cbmZ1bmN0aW9uIE5hdmlnYXRpb24ob3B0aW9ucykge1xuICAgIHV0aWwuc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbn1cblxuTmF2aWdhdGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICd0b3AtcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsJztcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgY2xhc3NOYW1lICsgJy1ncm91cCcsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fem9vbUluQnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLWluJywgbWFwLnpvb21Jbi5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLW91dCcsIG1hcC56b29tT3V0LmJpbmQobWFwKSk7XG4gICAgICAgIHRoaXMuX2NvbXBhc3MgPSB0aGlzLl9jcmVhdGVCdXR0b24oY2xhc3NOYW1lICsgJy1jb21wYXNzJywgbWFwLnJlc2V0Tm9ydGguYmluZChtYXApKTtcblxuICAgICAgICB2YXIgY29tcGFzc0NhbnZhcyA9IHRoaXMuX2NvbXBhc3NDYW52YXMgPSBET00uY3JlYXRlKCdjYW52YXMnLCBjbGFzc05hbWUgKyAnLWNvbXBhc3MtY2FudmFzJywgdGhpcy5fY29tcGFzcyk7XG4gICAgICAgIGNvbXBhc3NDYW52YXMuc3R5bGUuY3NzVGV4dCA9ICd3aWR0aDozMHB4OyBoZWlnaHQ6MzBweDsnO1xuICAgICAgICBjb21wYXNzQ2FudmFzLndpZHRoID0gMjYgKiAyO1xuICAgICAgICBjb21wYXNzQ2FudmFzLmhlaWdodCA9IDI2ICogMjtcblxuICAgICAgICB0aGlzLl9jb21wYXNzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uQ29tcGFzc0Rvd24uYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc01vdmUgPSB0aGlzLl9vbkNvbXBhc3NNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc1VwID0gdGhpcy5fb25Db21wYXNzVXAuYmluZCh0aGlzKTtcblxuICAgICAgICB0aGlzLl9jb21wYXNzQ3R4ID0gY29tcGFzc0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgIG1hcC5vbigncm90YXRlJywgdGhpcy5fZHJhd05vcnRoLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLl9kcmF3Tm9ydGgoKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfb25Db21wYXNzRG93bjogZnVuY3Rpb24oZSkge1xuICAgICAgICBET00uZGlzYWJsZURyYWcoKTtcblxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkNvbXBhc3NNb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQ29tcGFzc1VwKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG5cbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc01vdmU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLnNjcmVlblgsXG4gICAgICAgICAgICBkID0geCA8IDIgPyAtNSA6IC8vIGxlZnQgZWRnZSBvZiB0aGUgc2NyZWVuLCBjb250aW51ZSByb3RhdGluZ1xuICAgICAgICAgICAgICAgIHggPiB3aW5kb3cuc2NyZWVuLndpZHRoIC0gMiA/IDUgOiAvLyByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgKHggLSB0aGlzLl9wcmV2WCkgLyA0O1xuXG4gICAgICAgIHRoaXMuX21hcC5zZXRCZWFyaW5nKHRoaXMuX21hcC5nZXRCZWFyaW5nKCkgLSBkKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG4gICAgICAgIHRoaXMuX21vdmVkID0gdHJ1ZTtcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSxcblxuICAgIF9vbkNvbXBhc3NVcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQ29tcGFzc01vdmUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Db21wYXNzVXApO1xuICAgICAgICBET00uZW5hYmxlRHJhZygpO1xuXG4gICAgICAgIGlmICh0aGlzLl9tb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy5fbW92ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIERPTS5zdXBwcmVzc0NsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24oY2xhc3NOYW1lLCBmbikge1xuICAgICAgICB2YXIgYSA9IERPTS5jcmVhdGUoJ2J1dHRvbicsIGNsYXNzTmFtZSwgdGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkgeyBmbigpOyB9KTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfSxcblxuICAgIF9kcmF3Tm9ydGg6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmFkID0gMjAsXG4gICAgICAgICAgICB3aWR0aCA9IDgsXG4gICAgICAgICAgICBjZW50ZXIgPSAyNixcbiAgICAgICAgICAgIGFuZ2xlID0gdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSArIChNYXRoLlBJIC8gMiksXG4gICAgICAgICAgICBjdHggPSB0aGlzLl9jb21wYXNzQ3R4O1xuXG4gICAgICAgIHRoaXMuX2NvbXBhc3NDYW52YXMud2lkdGggPSB0aGlzLl9jb21wYXNzQ2FudmFzLndpZHRoO1xuXG4gICAgICAgIGN0eC50cmFuc2xhdGUoY2VudGVyLCBjZW50ZXIpO1xuICAgICAgICBjdHgucm90YXRlKGFuZ2xlKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnIzAwMCc7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbygtcmFkLCAwKTtcbiAgICAgICAgY3R4LmxpbmVUbygwLCB3aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gJyNiYmInO1xuICAgICAgICBjdHgubW92ZVRvKDAsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIHdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbyhyYWQsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSAnI2ZmZic7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSA0O1xuICAgICAgICBjdHgubW92ZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgd2lkdGgpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBJbnRlcmFjdGlvbiA9IHJlcXVpcmUoJy4vaW50ZXJhY3Rpb24nKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmdfYm91bmRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSGFuZGxlcnM7XG5cbmZ1bmN0aW9uIEhhbmRsZXJzKG1hcCkge1xuXG4gICAgdmFyIHJvdGF0ZUVuZDtcblxuICAgIHZhciBib3g7XG5cbiAgICB2YXIgaW5lcnRpYUxpbmVhcml0eSA9IDAuMixcbiAgICAgICAgaW5lcnRpYUVhc2luZyA9IHV0aWwuYmV6aWVyKDAsIDAsIGluZXJ0aWFMaW5lYXJpdHksIDEpO1xuXG4gICAgZnVuY3Rpb24gYm94em9vbUZpbmlzaCgpIHtcbiAgICAgICAgaWYgKGJveCkge1xuICAgICAgICAgICAgYm94LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoYm94KTtcbiAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgIGJveCA9IGZhbHNlO1xuICAgICAgICAgICAgRE9NLmVuYWJsZURyYWcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaW50ZXJhY3Rpb24gPSBuZXcgSW50ZXJhY3Rpb24obWFwLmdldENhbnZhcygpKVxuICAgICAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5sYXRMbmcgPSBtYXAudW5wcm9qZWN0KGUucG9pbnQpO1xuICAgICAgICAgICAgbWFwLmZpcmUoJ2NsaWNrJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZGJsY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnZGJsY2xpY2snLCBlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW91c2Vtb3ZlJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLnN0b3AoKTtcbiAgICAgICAgICAgIG1hcC5yZXNpemUoKTtcbiAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYgKGUuYWx0S2V5IHx8IGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHBhbiA9IDgwO1xuICAgICAgICAgICAgdmFyIHJvdGF0ZSA9IDI7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHpvb21CeSh6KSB7XG4gICAgICAgICAgICAgICAgbWFwLnpvb21UbyhNYXRoLnJvdW5kKG1hcC5nZXRab29tKCkpICsgKGUuc2hpZnRLZXkgPyAyIDogMSkgKiB6KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFuQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5wYW5CeSh2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcm90YXRlQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5zZXRCZWFyaW5nKG1hcC5nZXRCZWFyaW5nKCkgKyB2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDYxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTA3OlxuICAgICAgICAgICAgICAgIGNhc2UgMTcxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTg3OlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTg5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTA5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTczOlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoLTEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM3OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQnkoLXJvdGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5CeShbLXBhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzk6XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVCeShyb3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFuQnkoW3BhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzg6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCAtcGFuXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDA6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCBwYW5dKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIG1hcC5zdG9wKCk7XG4gICAgICAgICAgICB2YXIgbW91c2VMb2NhdGlvbiA9IG1hcC50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihlLnBvaW50LmFkZChlLm9mZnNldCkpO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5zZXRMb2NhdGlvbkF0UG9pbnQobW91c2VMb2NhdGlvbiwgZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbmVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5pbmVydGlhKSB7XG4gICAgICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29udmVydCB2ZWxvY2l0eSB0byBweC9zICYgYWRqdXN0IGZvciBpbmNyZWFzZWQgaW5pdGlhbCBhbmltYXRpb24gc3BlZWQgd2hlbiBlYXNpbmcgb3V0XG4gICAgICAgICAgICAgICAgdmFyIHZlbG9jaXR5ID0gZS5pbmVydGlhLm11bHQoMTAwMCAqIGluZXJ0aWFMaW5lYXJpdHkpLFxuICAgICAgICAgICAgICAgICAgICBzcGVlZCA9IHZlbG9jaXR5Lm1hZygpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heFNwZWVkID0gNDAwMDsgLy8gcHgvc1xuXG4gICAgICAgICAgICAgICAgaWYgKHNwZWVkID49IG1heFNwZWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwZWVkID0gbWF4U3BlZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZlbG9jaXR5Ll91bml0KCkuX211bHQobWF4U3BlZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBkZWNlbGVyYXRpb24gPSA4MDAwLCAvLyBweC9zXjJcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzcGVlZCAvIChkZWNlbGVyYXRpb24gKiBpbmVydGlhTGluZWFyaXR5KSxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gdmVsb2NpdHkubXVsdCgtZHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gICAgICAgICAgICAgICAgbWFwLnBhbkJ5KG9mZnNldCwge1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24gKiAxMDAwLFxuICAgICAgICAgICAgICAgICAgICBlYXNpbmc6IGluZXJ0aWFFYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIG5vTW92ZVN0YXJ0OiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignem9vbScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIFNjYWxlIGJ5IHNpZ21vaWQgb2Ygc2Nyb2xsIHdoZWVsIGRlbHRhLlxuICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAvICgxICsgTWF0aC5leHAoLU1hdGguYWJzKGUuZGVsdGEgLyAxMDApKSk7XG4gICAgICAgICAgICBpZiAoZS5kZWx0YSA8IDAgJiYgc2NhbGUgIT09IDApIHNjYWxlID0gMSAvIHNjYWxlO1xuXG4gICAgICAgICAgICB2YXIgZnJvbVNjYWxlID0gbWFwLmVhc2UgJiYgaXNGaW5pdGUoZS5kZWx0YSkgPyBtYXAuZWFzZS50byA6IG1hcC50cmFuc2Zvcm0uc2NhbGUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSAhaXNGaW5pdGUoZS5kZWx0YSkgPyA4MDAgOiAwO1xuXG4gICAgICAgICAgICBtYXAuem9vbVRvKG1hcC50cmFuc2Zvcm0uc2NhbGVab29tKGZyb21TY2FsZSAqIHNjYWxlKSwge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICBhcm91bmQ6IG1hcC51bnByb2plY3QoZS5wb2ludClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3JvdGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIHZhciBjZW50ZXIgPSBtYXAudHJhbnNmb3JtLmNlbnRlclBvaW50LCAvLyBDZW50ZXIgb2Ygcm90YXRpb25cbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyID0gZS5zdGFydC5zdWIoY2VudGVyKSxcbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyRGlzdCA9IHN0YXJ0VG9DZW50ZXIubWFnKCk7XG5cbiAgICAgICAgICAgIG1hcC5yb3RhdGluZyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBjbGljayB3YXMgdG9vIGNsb3NlIHRvIHRoZSBjZW50ZXIsIG1vdmUgdGhlIGNlbnRlciBvZiByb3RhdGlvbiBieSAyMDAgcGl4ZWxzXG4gICAgICAgICAgICAvLyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBjbGljay5cbiAgICAgICAgICAgIGlmIChzdGFydFRvQ2VudGVyRGlzdCA8IDIwMCkge1xuICAgICAgICAgICAgICAgIGNlbnRlciA9IGUuc3RhcnQuYWRkKG5ldyBQb2ludCgtMjAwLCAwKS5fcm90YXRlKHN0YXJ0VG9DZW50ZXIuYW5nbGUoKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYmVhcmluZ0RpZmYgPSBlLnByZXYuc3ViKGNlbnRlcikuYW5nbGVXaXRoKGUuY3VycmVudC5zdWIoY2VudGVyKSkgLyBNYXRoLlBJICogMTgwO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5iZWFyaW5nID0gbWFwLmdldEJlYXJpbmcoKSAtIGJlYXJpbmdEaWZmO1xuXG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHJvdGF0ZUVuZCk7XG4gICAgICAgICAgICByb3RhdGVFbmQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBtYXAucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBtYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgICAgICB9LCAyMDApO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2JveHpvb21zdGFydCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghYm94KSB7XG4gICAgICAgICAgICAgICAgYm94ID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWJveHpvb20nLCBtYXAuZ2V0Q29udGFpbmVyKCkpO1xuICAgICAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QuYWRkKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgICAgICBtYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gICAgICAgICAgICAgICAgRE9NLmRpc2FibGVEcmFnKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBtaW5YID0gTWF0aC5taW4oZS5zdGFydC54LCBlLmN1cnJlbnQueCk7XG4gICAgICAgICAgICB2YXIgbWF4WCA9IE1hdGgubWF4KGUuc3RhcnQueCwgZS5jdXJyZW50LngpO1xuICAgICAgICAgICAgdmFyIG1pblkgPSBNYXRoLm1pbihlLnN0YXJ0LnksIGUuY3VycmVudC55KTtcbiAgICAgICAgICAgIHZhciBtYXhZID0gTWF0aC5tYXgoZS5zdGFydC55LCBlLmN1cnJlbnQueSk7XG5cbiAgICAgICAgICAgIERPTS5zZXRUcmFuc2Zvcm0oYm94LCAndHJhbnNsYXRlKCcgKyBtaW5YICsgJ3B4LCcgKyBtaW5ZICsgJ3B4KScpO1xuICAgICAgICAgICAgYm94LnN0eWxlLndpZHRoID0gKG1heFggLSBtaW5YKSArICdweCc7XG4gICAgICAgICAgICBib3guc3R5bGUuaGVpZ2h0ID0gKG1heFkgLSBtaW5ZKSArICdweCc7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGJveHpvb21GaW5pc2goKTtcblxuICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICAgICAgbWFwLnVucHJvamVjdChlLnN0YXJ0KSxcbiAgICAgICAgICAgICAgICBtYXAudW5wcm9qZWN0KGUuY3VycmVudClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzLCB7IGxpbmVhcjogdHJ1ZSB9KS5maXJlKCdib3h6b29tZW5kJywge1xuICAgICAgICAgICAgICAgIGJveFpvb21Cb3VuZHM6IGJvdW5kc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWNhbmNlbCcsIGJveHpvb21GaW5pc2gpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogQWRkcyBwb3NpdGlvbmFsIGNvb3JkaW5hdGVzIHRvIFVSTCBoYXNoZXMuIFBhc3NlZCBhcyBhbiBvcHRpb24gdG8gdGhlIG1hcCBvYmplY3RcbiAqXG4gKiBAY2xhc3MgbWFwYm94Z2wuSGFzaFxuICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEhhc2g7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmZ1bmN0aW9uIEhhc2goKSB7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ19vbkhhc2hDaGFuZ2UnLFxuICAgICAgICAnX3VwZGF0ZUhhc2gnXG4gICAgXSwgdGhpcyk7XG59XG5cbkhhc2gucHJvdG90eXBlID0ge1xuICAgIC8qIE1hcCBlbGVtZW50IHRvIGxpc3RlbiBmb3IgY29vcmRpbmF0ZSBjaGFuZ2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwXG4gICAgICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVIYXNoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qIFJlbW92ZXMgaGFzaFxuICAgICAqXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlZW5kJywgdGhpcy5fdXBkYXRlSGFzaCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9tYXA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25IYXNoQ2hhbmdlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGxvYyA9IGxvY2F0aW9uLmhhc2gucmVwbGFjZSgnIycsICcnKS5zcGxpdCgnLycpO1xuICAgICAgICBpZiAobG9jLmxlbmd0aCA+PSAzKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAuanVtcFRvKHtcbiAgICAgICAgICAgICAgICBjZW50ZXI6IFsrbG9jWzFdLCArbG9jWzJdXSxcbiAgICAgICAgICAgICAgICB6b29tOiArbG9jWzBdLFxuICAgICAgICAgICAgICAgIGJlYXJpbmc6ICsobG9jWzNdIHx8IDApXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUhhc2g6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY2VudGVyID0gdGhpcy5fbWFwLmdldENlbnRlcigpLFxuICAgICAgICAgICAgem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCksXG4gICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5fbWFwLmdldEJlYXJpbmcoKSxcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IE1hdGgubWF4KDAsIE1hdGguY2VpbChNYXRoLmxvZyh6b29tKSAvIE1hdGguTE4yKSksXG5cbiAgICAgICAgICAgIGhhc2ggPSAnIycgKyAoTWF0aC5yb3VuZCh6b29tICogMTAwKSAvIDEwMCkgK1xuICAgICAgICAgICAgICAgICcvJyArIGNlbnRlci5sYXQudG9GaXhlZChwcmVjaXNpb24pICtcbiAgICAgICAgICAgICAgICAnLycgKyBjZW50ZXIubG5nLnRvRml4ZWQocHJlY2lzaW9uKSArXG4gICAgICAgICAgICAgICAgKGJlYXJpbmcgPyAnLycgKyAoTWF0aC5yb3VuZChiZWFyaW5nICogMTApIC8gMTApIDogJycpO1xuXG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSgnJywgJycsIGhhc2gpO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcmFjdGlvbjtcblxuLyoqXG4gKiBNb3VzZSBldmVudFxuICpcbiAqIEBldmVudCBNYXAjbW91c2Vtb3ZlXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtFdmVudH0gb3JpZ2luYWxFdmVudCB0aGUgb3JpZ2luYWwgRE9NIGV2ZW50XG4gKi9cblxuLyoqXG4gKiBEb3VibGUgY2xpY2sgZXZlbnQuXG4gKlxuICogQGV2ZW50IE1hcCNkYmxjbGlja1xuICogQHR5cGUge09iamVjdH1cbiAqIEBwcm9wZXJ0eSB7UG9pbnR9IHBvaW50IHRoZSBwaXhlbCBsb2NhdGlvbiBvZiB0aGUgZXZlbnRcbiAqL1xuXG4vKipcbiAqIFBhbiBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtQb2ludH0gb2Zmc2V0IGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBtb3ZlbWVudCBmcm9tIHRoZSBwcmV2aW91cyBtYXAgbG9jYXRpb24gdG8gdGhlIGN1cnJlbnQgb25lLlxuICovXG5cbi8qKlxuICogUGFuIGVuZCBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuZW5kXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlbG9jaXR5IGEgbWVhc3VyZSBvZiBob3cgbXVjaCBpbmVydGlhIHdhcyByZWNvcmRlZCBpbiB0aGlzIHBhbiBtb3Rpb25cbiAqL1xuXG5mdW5jdGlvbiBJbnRlcmFjdGlvbihlbCkge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHRoaXM7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuXG4gICAgdmFyIHJvdGF0aW5nID0gZmFsc2UsXG4gICAgICAgIHBhbm5lZCA9IGZhbHNlLFxuICAgICAgICBib3h6b29tID0gZmFsc2UsXG4gICAgICAgIGZpcnN0UG9zID0gbnVsbCxcbiAgICAgICAgcG9zID0gbnVsbCxcbiAgICAgICAgaW5lcnRpYSA9IG51bGwsXG4gICAgICAgIG5vdztcblxuICAgIGZ1bmN0aW9uIG1vdXNlUG9zKGUpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChcbiAgICAgICAgICAgIGUuY2xpZW50WCAtIHJlY3QubGVmdCAtIGVsLmNsaWVudExlZnQsXG4gICAgICAgICAgICBlLmNsaWVudFkgLSByZWN0LnRvcCAtIGVsLmNsaWVudFRvcCk7XG4gICAgfVxuXG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbihldikge1xuICAgICAgICByb3RhdGluZyA9IHRydWU7XG4gICAgICAgIGZpcnN0UG9zID0gcG9zID0gbW91c2VQb3MoZXYpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93biwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbm1vdXNldXAsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbm1vdXNlbW92ZSwgZmFsc2UpO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25jbGljaywgZmFsc2UpO1xuICAgIHNjcm9sbHdoZWVsKHpvb20pO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kb3VibGVjbGljaywgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUsIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywga2V5ZG93biwgZmFsc2UpO1xuXG4gICAgZnVuY3Rpb24gem9vbSh0eXBlLCBkZWx0YSwgcG9pbnQpIHtcbiAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnem9vbScsIHtcbiAgICAgICAgICAgIHNvdXJjZTogdHlwZSxcbiAgICAgICAgICAgIGRlbHRhOiBkZWx0YSxcbiAgICAgICAgICAgIHBvaW50OiBwb2ludFxuICAgICAgICB9KTtcbiAgICAgICAgaW5lcnRpYSA9IG51bGw7XG4gICAgICAgIG5vdyA9IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2NsaWNrJywge3BvaW50OiBwb2ludCwgb3JpZ2luYWxFdmVudDogZXZ9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3VzZW1vdmUocG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ21vdXNlbW92ZScsIHtwb2ludDogcG9pbnQsIG9yaWdpbmFsRXZlbnQ6IGV2fSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFuKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBwb3Muc3ViKHBvaW50KTtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3BhbicsIHtvZmZzZXQ6IG9mZnNldCwgcG9pbnQ6IHBvaW50fSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCBhbiBhdmVyYWdlZCB2ZXJzaW9uIG9mIHRoaXMgbW92ZW1lbnQgdG8gdGhlIGluZXJ0aWEgdmVjdG9yXG4gICAgICAgICAgICBpZiAoaW5lcnRpYSkge1xuICAgICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBub3c7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRpbWVzIGl0J3MgMCBhZnRlciBzb21lIGVycmF0aWMgcGFuaW5nXG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lID0gZHVyYXRpb24gKyBub3c7XG4gICAgICAgICAgICAgICAgICAgIGluZXJ0aWEucHVzaChbdGltZSwgcG9pbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGluZXJ0aWEubGVuZ3RoID4gMiAmJiB0aW1lIC0gaW5lcnRpYVswXVswXSA+IDEwMCkgaW5lcnRpYS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmVydGlhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgcG9zID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUoKSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3Jlc2l6ZScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtleWRvd24oZXYpIHtcbiAgICAgICAgaWYgKGJveHpvb20gJiYgZXYua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21jYW5jZWwnKTtcbiAgICAgICAgICAgIGJveHpvb20gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2tleWRvd24nLCBldik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcm90YXRlKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3JvdGF0ZScsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogZmlyc3RQb3MsXG4gICAgICAgICAgICAgICAgcHJldjogcG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IHBvaW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvcyA9IHBvaW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG91YmxlY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2RibGNsaWNrJywge1xuICAgICAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZWRvd24oZXYpIHtcbiAgICAgICAgZmlyc3RQb3MgPSBwb3MgPSBtb3VzZVBvcyhldik7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2Rvd24nKTtcbiAgICAgICAgaWYgKGV2LnNoaWZ0S2V5IHx8ICgoZXYud2hpY2ggPT09IDEpICYmIChldi5idXR0b24gPT09IDEpKSkge1xuICAgICAgICAgIGJveHpvb20gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZXVwKGV2KSB7XG4gICAgICAgIHBhbm5lZCA9IHBvcyAmJiBmaXJzdFBvcyAmJiAocG9zLnggIT09IGZpcnN0UG9zLnggfHwgcG9zLnkgIT09IGZpcnN0UG9zLnkpO1xuXG4gICAgICAgIHJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgIHBvcyA9IG51bGw7XG5cbiAgICAgICAgaWYgKGJveHpvb20pIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21lbmQnLCB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGZpcnN0UG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IG1vdXNlUG9zKGV2KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBib3h6b29tID0gZmFsc2U7XG5cbiAgICAgICAgfSBlbHNlIGlmIChpbmVydGlhICYmIGluZXJ0aWEubGVuZ3RoID49IDIgJiYgbm93ID4gRGF0ZS5ub3coKSAtIDEwMCkge1xuICAgICAgICAgICAgdmFyIGxhc3QgPSBpbmVydGlhW2luZXJ0aWEubGVuZ3RoIC0gMV0sXG4gICAgICAgICAgICAgICAgZmlyc3QgPSBpbmVydGlhWzBdLFxuICAgICAgICAgICAgICAgIHZlbG9jaXR5ID0gbGFzdFsxXS5zdWIoZmlyc3RbMV0pLmRpdihsYXN0WzBdIC0gZmlyc3RbMF0pO1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgncGFuZW5kJywge2luZXJ0aWE6IHZlbG9jaXR5fSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChwb3MpIHtcbiAgICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdwYW5lbmQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluZXJ0aWEgPSBudWxsO1xuICAgICAgICBub3cgPSBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubW91c2Vtb3ZlKGV2KSB7XG4gICAgICAgIHZhciBwb2ludCA9IG1vdXNlUG9zKGV2KTtcblxuICAgICAgICBpZiAoYm94em9vbSkge1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnYm94em9vbXN0YXJ0Jywge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBmaXJzdFBvcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50OiBwb2ludFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyb3RhdGluZykge1xuICAgICAgICAgICAgcm90YXRlKHBvaW50KTtcblxuICAgICAgICB9IGVsc2UgaWYgKHBvcykge1xuICAgICAgICAgICAgcGFuKHBvaW50KTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhcmdldCA9IGV2LnRvRWxlbWVudCB8fCBldi50YXJnZXQ7XG4gICAgICAgICAgICB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldCAhPT0gZWwgJiYgdGFyZ2V0LnBhcmVudE5vZGUpIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICBtb3VzZW1vdmUocG9pbnQsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uY2xpY2soZXYpIHtcbiAgICAgICAgaWYgKCFwYW5uZWQpIGNsaWNrKG1vdXNlUG9zKGV2KSwgZXYpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uZG91YmxlY2xpY2soZXYpIHtcbiAgICAgICAgZG91YmxlY2xpY2sobW91c2VQb3MoZXYpLCBldik7XG4gICAgICAgIHpvb20oJ3doZWVsJywgSW5maW5pdHkgKiAoZXYuc2hpZnRLZXkgPyAtMSA6IDEpLCBtb3VzZVBvcyhldikpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbHdoZWVsKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmaXJlZm94ID0gL0ZpcmVmb3gvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgc2FmYXJpID0gL1NhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIS9DaHJvbShpdW18ZSkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgdGltZSA9IHdpbmRvdy5wZXJmb3JtYW5jZSB8fCBEYXRlO1xuXG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgd2hlZWwsIGZhbHNlKTtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V3aGVlbCcsIG1vdXNld2hlZWwsIGZhbHNlKTtcblxuICAgICAgICB2YXIgbGFzdEV2ZW50ID0gMDtcblxuICAgICAgICB2YXIgdHlwZSA9IG51bGw7XG4gICAgICAgIHZhciB0eXBlVGltZW91dCA9IG51bGw7XG4gICAgICAgIHZhciBpbml0aWFsVmFsdWUgPSBudWxsO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNjcm9sbCh2YWx1ZSwgZXYpIHtcbiAgICAgICAgICAgIHZhciBzdGFtcCA9IHRpbWUubm93KCk7XG4gICAgICAgICAgICB2YXIgdGltZURlbHRhID0gc3RhbXAgLSBsYXN0RXZlbnQ7XG4gICAgICAgICAgICBsYXN0RXZlbnQgPSBzdGFtcDtcblxuICAgICAgICAgICAgdmFyIHBvaW50ID0gbW91c2VQb3MoZXYpO1xuXG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IDAgJiYgKHZhbHVlICUgNC4wMDAyNDQxNDA2MjUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIG1vdXNlIHdoZWVsIGV2ZW50LlxuICAgICAgICAgICAgICAgIHR5cGUgPSAnd2hlZWwnO1xuICAgICAgICAgICAgICAgIC8vIE5vcm1hbGl6ZSB0aGlzIHZhbHVlIHRvIG1hdGNoIHRyYWNrcGFkLlxuICAgICAgICAgICAgICAgIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSAvIDQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSAhPT0gMCAmJiBNYXRoLmFicyh2YWx1ZSkgPCA0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIHRyYWNrcGFkIGV2ZW50IGJlY2F1c2UgaXQgaXMgc28gc21hbGwuXG4gICAgICAgICAgICAgICAgdHlwZSA9ICd0cmFja3BhZCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRpbWVEZWx0YSA+IDQwMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgbGlrZWx5IGEgbmV3IHNjcm9sbCBhY3Rpb24uXG4gICAgICAgICAgICAgICAgdHlwZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgLy8gU3RhcnQgYSB0aW1lb3V0IGluIGNhc2UgdGhpcyB3YXMgYSBzaW5ndWxhciBldmVudCwgYW5kIGRlbHkgaXRcbiAgICAgICAgICAgICAgICAvLyBieSB1cCB0byA0MG1zLlxuICAgICAgICAgICAgICAgIHR5cGVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICd3aGVlbCc7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHR5cGUsIC1pbml0aWFsVmFsdWUsIHBvaW50KTtcbiAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVwZWF0aW5nIGV2ZW50LCBidXQgd2UgZG9uJ3Qga25vdyB0aGUgdHlwZSBvZiBldmVudFxuICAgICAgICAgICAgICAgIC8vIGp1c3QgeWV0LiBJZiB0aGUgZGVsdGEgcGVyIHRpbWUgaXMgc21hbGwsIHdlIGFzc3VtZSBpdCdzIGFcbiAgICAgICAgICAgICAgICAvLyBmYXN0IHRyYWNrcGFkOyBvdGhlcndpc2Ugd2Ugc3dpdGNoIGludG8gd2hlZWwgbW9kZS5cbiAgICAgICAgICAgICAgICB0eXBlID0gKE1hdGguYWJzKHRpbWVEZWx0YSAqIHZhbHVlKSA8IDIwMCkgPyAndHJhY2twYWQnIDogJ3doZWVsJztcblxuICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgZGVsYXllZCBldmVudCBpc24ndCBmaXJlZCBhZ2FpbiwgYmVjYXVzZSB3ZVxuICAgICAgICAgICAgICAgIC8vIGFjY3VtdWxhdGUgdGhlIHByZXZpb3VzIGV2ZW50ICh3aGljaCB3YXMgbGVzcyB0aGFuIDQwbXMgYWdvKSBpbnRvXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBldmVudC5cbiAgICAgICAgICAgICAgICBpZiAodHlwZVRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHR5cGVUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZVRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBpbml0aWFsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTbG93IGRvd24gem9vbSBpZiBzaGlmdCBrZXkgaXMgaGVsZCBmb3IgbW9yZSBwcmVjaXNlIHpvb21pbmdcbiAgICAgICAgICAgIGlmIChldi5zaGlmdEtleSAmJiB2YWx1ZSkgdmFsdWUgPSB2YWx1ZSAvIDQ7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZmlyZSB0aGUgY2FsbGJhY2sgaWYgd2UgYWN0dWFsbHkga25vdyB3aGF0IHR5cGUgb2Ygc2Nyb2xsaW5nXG4gICAgICAgICAgICAvLyBkZXZpY2UgdGhlIHVzZXIgdXNlcy5cbiAgICAgICAgICAgIGlmICh0eXBlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sodHlwZSwgLXZhbHVlLCBwb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gZS5kZWx0YVk7XG4gICAgICAgICAgICAvLyBGaXJlZm94IGRvdWJsZXMgdGhlIHZhbHVlcyBvbiByZXRpbmEgc2NyZWVucy4uLlxuICAgICAgICAgICAgaWYgKGZpcmVmb3ggJiYgZS5kZWx0YU1vZGUgPT09IHdpbmRvdy5XaGVlbEV2ZW50LkRPTV9ERUxUQV9QSVhFTCkgZGVsdGFZIC89IGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gd2luZG93LldoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIGRlbHRhWSAqPSA0MDtcbiAgICAgICAgICAgIHNjcm9sbChkZWx0YVksIGUpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2V3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gLWUud2hlZWxEZWx0YVk7XG4gICAgICAgICAgICBpZiAoc2FmYXJpKSBkZWx0YVkgPSBkZWx0YVkgLyAzO1xuICAgICAgICAgICAgc2Nyb2xsKGRlbHRhWSwgZSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbkludGVyYWN0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRlZCk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBDYW52YXMgPSByZXF1aXJlKCcuLi91dGlsL2NhbnZhcycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG5cbnZhciBTdHlsZSA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlJyk7XG52YXIgQW5pbWF0aW9uTG9vcCA9IHJlcXVpcmUoJy4uL3N0eWxlL2FuaW1hdGlvbl9sb29wJyk7XG52YXIgUGFpbnRlciA9IHJlcXVpcmUoJy4uL3JlbmRlci9wYWludGVyJyk7XG5cbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuLi9nZW8vdHJhbnNmb3JtJyk7XG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xudmFyIEhhbmRsZXJzID0gcmVxdWlyZSgnLi9oYW5kbGVycycpO1xudmFyIENhbWVyYSA9IHJlcXVpcmUoJy4vY2FtZXJhJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBMYXRMbmdCb3VuZHMgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQXR0cmlidXRpb24gPSByZXF1aXJlKCcuL2NvbnRyb2wvYXR0cmlidXRpb24nKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbWFwIGluc3RhbmNlLlxuICogQGNsYXNzIE1hcFxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbnRhaW5lciBIVE1MIGVsZW1lbnQgdG8gaW5pdGlhbGl6ZSB0aGUgbWFwIGluIChvciBlbGVtZW50IGlkIGFzIHN0cmluZylcbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW5ab29tPTBdIE1pbmltdW0gem9vbSBvZiB0aGUgbWFwXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4Wm9vbT0yMF0gTWF4aW11bSB6b29tIG9mIHRoZSBtYXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnN0eWxlIE1hcCBzdHlsZSBhbmQgZGF0YSBzb3VyY2UgZGVmaW5pdGlvbiAoZWl0aGVyIGEgSlNPTiBvYmplY3Qgb3IgYSBKU09OIFVSTCksIGRlc2NyaWJlZCBpbiB0aGUgW3N0eWxlIHJlZmVyZW5jZV0oaHR0cHM6Ly9tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuaGFzaD1mYWxzZV0gSWYgYHRydWVgLCB0aGUgbWFwIHdpbGwgdHJhY2sgYW5kIHVwZGF0ZSB0aGUgcGFnZSBVUkwgYWNjb3JkaW5nIHRvIG1hcCBwb3NpdGlvblxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbnRlcmFjdGl2ZT10cnVlXSBJZiBgZmFsc2VgLCBubyBtb3VzZSwgdG91Y2gsIG9yIGtleWJvYXJkIGxpc3RlbmVycyBhcmUgYXR0YWNoZWQgdG8gdGhlIG1hcCwgc28gaXQgd2lsbCBub3QgcmVzcG9uZCB0byBpbnB1dFxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5jbGFzc2VzIFN0eWxlIGNsYXNzIG5hbWVzIHdpdGggd2hpY2ggdG8gaW5pdGlhbGl6ZSB0aGUgbWFwXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9ZmFsc2VdIElmIGB0cnVlYCwgbWFwIGNyZWF0aW9uIHdpbGwgZmFpbCBpZiB0aGUgaW1wbGVtZW50YXRpb24gZGV0ZXJtaW5lcyB0aGF0IHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgY3JlYXRlZCBXZWJHTCBjb250ZXh0IHdvdWxkIGJlIGRyYW1hdGljYWxseSBsb3dlciB0aGFuIGV4cGVjdGVkLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXI9ZmFsc2VdIElmIGB0cnVlYCwgVGhlIG1hcHMgY2FudmFzIGNhbiBiZSBleHBvcnRlZCB0byBhIFBORyB1c2luZyBgbWFwLmdldENhbnZhcygpLnRvRGF0YVVSTCgpO2AuIFRoaXMgaXMgZmFsc2UgYnkgZGVmYXVsdCBhcyBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgbWFwID0gbmV3IG1hcGJveGdsLk1hcCh7XG4gKiAgIGNvbnRhaW5lcjogJ21hcCcsXG4gKiAgIGNlbnRlcjogWzM3Ljc3MjUzNywgLTEyMi40MjA2NzldLFxuICogICB6b29tOiAxMyxcbiAqICAgc3R5bGU6IHN0eWxlX29iamVjdCxcbiAqICAgaGFzaDogdHJ1ZVxuICogfSk7XG4gKi9cbnZhciBNYXAgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB1dGlsLmluaGVyaXQodGhpcy5vcHRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuYW5pbWF0aW9uTG9vcCA9IG5ldyBBbmltYXRpb25Mb29wKCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSBuZXcgVHJhbnNmb3JtKG9wdGlvbnMubWluWm9vbSwgb3B0aW9ucy5tYXhab29tKTtcblxuICAgIGlmIChvcHRpb25zLm1heEJvdW5kcykge1xuICAgICAgICB2YXIgYiA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KG9wdGlvbnMubWF4Qm91bmRzKTtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2UgPSBbYi5nZXRTb3V0aCgpLCBiLmdldE5vcnRoKCldO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZSA9IFtiLmdldFdlc3QoKSwgYi5nZXRFYXN0KCldO1xuICAgIH1cblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFN0eWxlRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRTb3VyY2VFdmVudCcsXG4gICAgICAgICdfZm9yd2FyZExheWVyRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRUaWxlRXZlbnQnLFxuICAgICAgICAnX29uU3R5bGVMb2FkJyxcbiAgICAgICAgJ19vblN0eWxlQ2hhbmdlJyxcbiAgICAgICAgJ19vblNvdXJjZUFkZCcsXG4gICAgICAgICdfb25Tb3VyY2VSZW1vdmUnLFxuICAgICAgICAnX29uU291cmNlVXBkYXRlJyxcbiAgICAgICAgJ3VwZGF0ZScsXG4gICAgICAgICdyZW5kZXInXG4gICAgXSwgdGhpcyk7XG5cbiAgICB0aGlzLl9zZXR1cENvbnRhaW5lcigpO1xuICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuXG4gICAgdGhpcy5vbignbW92ZScsIHRoaXMudXBkYXRlKTtcbiAgICB0aGlzLm9uKCd6b29tJywgdGhpcy51cGRhdGUuYmluZCh0aGlzLCB0cnVlKSk7XG4gICAgdGhpcy5vbignbW92ZWVuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3Auc2V0KDMwMCk7IC8vIHRleHQgZmFkaW5nXG4gICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuaGFuZGxlcnMgPSBvcHRpb25zLmludGVyYWN0aXZlICYmIG5ldyBIYW5kbGVycyh0aGlzKTtcblxuICAgIHRoaXMuX2hhc2ggPSBvcHRpb25zLmhhc2ggJiYgKG5ldyBIYXNoKCkpLmFkZFRvKHRoaXMpO1xuICAgIC8vIGRvbid0IHNldCBwb3NpdGlvbiBmcm9tIG9wdGlvbnMgaWYgc2V0IHRocm91Z2ggaGFzaFxuICAgIGlmICghdGhpcy5faGFzaCB8fCAhdGhpcy5faGFzaC5fb25IYXNoQ2hhbmdlKCkpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8ob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VzID0ge307XG4gICAgdGhpcy5zdGFja3MgPSB7fTtcbiAgICB0aGlzLl9jbGFzc2VzID0ge307XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgaWYgKG9wdGlvbnMuY2xhc3NlcykgdGhpcy5zZXRDbGFzc2VzKG9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgaWYgKG9wdGlvbnMuc3R5bGUpIHRoaXMuc2V0U3R5bGUob3B0aW9ucy5zdHlsZSk7XG4gICAgaWYgKG9wdGlvbnMuYXR0cmlidXRpb25Db250cm9sKSB0aGlzLmFkZENvbnRyb2wobmV3IEF0dHJpYnV0aW9uKCkpO1xufTtcblxudXRpbC5leHRlbmQoTWFwLnByb3RvdHlwZSwgRXZlbnRlZCk7XG51dGlsLmV4dGVuZChNYXAucHJvdG90eXBlLCBDYW1lcmEucHJvdG90eXBlKTtcbnV0aWwuZXh0ZW5kKE1hcC5wcm90b3R5cGUsIC8qKiBAbGVuZHMgTWFwLnByb3RvdHlwZSAqL3tcblxuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICAgIHpvb206IDAsXG4gICAgICAgIGJlYXJpbmc6IDAsXG4gICAgICAgIHBpdGNoOiAwLFxuXG4gICAgICAgIG1pblpvb206IDAsXG4gICAgICAgIG1heFpvb206IDIwLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICBoYXNoOiBmYWxzZSxcblxuICAgICAgICBhdHRyaWJ1dGlvbkNvbnRyb2w6IHRydWUsXG5cbiAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogZmFsc2UsXG4gICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2VcbiAgICB9LFxuXG4gICAgYWRkQ29udHJvbDogZnVuY3Rpb24oY29udHJvbCkge1xuICAgICAgICBjb250cm9sLmFkZFRvKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHR5cGVkZWYge09iamVjdH0gW3N0eWxlT3B0aW9uc11cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtzdHlsZU9wdGlvbnMudHJhbnNpdGlvbj10cnVlXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHN0eWxlIGNsYXNzIHRvIGEgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2xhc3MgbmFtZSBvZiBzdHlsZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7c3R5bGVPcHRpb25zfSBvcHRpb25zXG4gICAgICogQGZpcmVzIGNoYW5nZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZENsYXNzOiBmdW5jdGlvbihrbGFzcywgb3B0aW9ucykge1xuICAgICAgICBpZiAodGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc10gPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIHN0eWxlIGNsYXNzIGZyb20gYSBtYXBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBuYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghdGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBhZGQgbW9yZSB0aGFuIG9uZSBjbGFzc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBrbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0Q2xhc3NlczogZnVuY3Rpb24oa2xhc3Nlcywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLl9jbGFzc2VzID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc2VzW2ldXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcywgb3B0aW9ucyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoZWNrIHdoZXRoZXIgYSBzdHlsZSBjbGFzcyBpcyBhY3RpdmVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBOYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgYWN0aXZlIHN0eWxlIGNsYXNzZXNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldENsYXNzZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fY2xhc3Nlcyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIERldGVjdCB0aGUgbWFwJ3MgbmV3IHdpZHRoIGFuZCBoZWlnaHQgYW5kIHJlc2l6ZSBpdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlc2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDAsIGhlaWdodCA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGggfHwgNDAwO1xuICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAzMDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jYW52YXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMudHJhbnNmb3JtLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0uX2NvbnN0cmFpbigpO1xuXG4gICAgICAgIHRoaXMucGFpbnRlci5yZXNpemUod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIC5maXJlKCdtb3Zlc3RhcnQnKVxuICAgICAgICAgICAgLmZpcmUoJ21vdmUnKVxuICAgICAgICAgICAgLmZpcmUoJ3Jlc2l6ZScpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1hcCdzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN9XG4gICAgICovXG4gICAgZ2V0Qm91bmRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyBQb2ludCgwLCAwKSksXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKHRoaXMudHJhbnNmb3JtLnNpemUpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHBpeGVsIGNvb3JkaW5hdGVzIChyZWxhdGl2ZSB0byBtYXAgY29udGFpbmVyKSBnaXZlbiBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IGB4YCBhbmQgYHlgIGNvb3JkaW5hdGVzXG4gICAgICovXG4gICAgcHJvamVjdDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybS5sb2NhdGlvblBvaW50KExhdExuZy5jb252ZXJ0KGxhdGxuZykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGdpdmVuIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHBvaW50IFt4LCB5XSBwaXhlbCBjb29yZGluYXRlc1xuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgdW5wcm9qZWN0OiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZmVhdHVyZXMgYXQgYSBwb2ludCAoW3gsIHldKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBwb2ludCBbeCwgeV0gcGl4ZWwgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwYXJhbXMucmFkaXVzPTBdIE9wdGlvbmFsLiBSYWRpdXMgaW4gcGl4ZWxzIHRvIHNlYXJjaCBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMubGF5ZXIgT3B0aW9uYWwuIE9ubHkgcmV0dXJuIGZlYXR1cmVzIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMudHlwZSBPcHRpb25hbC4gRWl0aGVyIGByYXN0ZXJgIG9yIGB2ZWN0b3JgXG4gICAgICogQHBhcmFtIHtmZWF0dXJlc0F0Q2FsbGJhY2t9IGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcmVzcG9uc2VcbiAgICAgKlxuICAgICAqIEBjYWxsYmFjayBmZWF0dXJlc0F0Q2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge09iamVjdHxudWxsfSBlcnIgRXJyb3IgX0lmIGFueV9cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmZWF0dXJlcyBEaXNwbGF5cyBhIEpTT04gYXJyYXkgb2YgZmVhdHVyZXMgZ2l2ZW4gdGhlIHBhc3NlZCBwYXJhbWV0ZXJzIG9mIGBmZWF0dXJlc0F0YFxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5mZWF0dXJlc0F0KFsxMCwgMjBdLCB7IHJhZGl1czogMTAgfSwgZnVuY3Rpb24oZXJyLCBmZWF0dXJlcykge1xuICAgICAqICAgY29uc29sZS5sb2coZmVhdHVyZXMpO1xuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBjb29yZCA9IHRoaXMudHJhbnNmb3JtLnBvaW50Q29vcmRpbmF0ZShQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgICAgIHRoaXMuc3R5bGUuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgbWFwJ3Mgc3R5bGUgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3R5bGUgQSBzdHlsZSBvYmplY3QgZm9ybWF0dGVkIGFzIEpTT05cbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRTdHlsZTogZnVuY3Rpb24oc3R5bGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGVcbiAgICAgICAgICAgICAgICAub2ZmKCdsb2FkJywgdGhpcy5fb25TdHlsZUxvYWQpXG4gICAgICAgICAgICAgICAgLm9mZignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vblN0eWxlQ2hhbmdlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ3NvdXJjZS5hZGQnLCB0aGlzLl9vblNvdXJjZUFkZClcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmxvYWQnLCB0aGlzLl9vblNvdXJjZVVwZGF0ZSlcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UuZXJyb3InLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLmFkZCcsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCd0aWxlLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLl9yZW1vdmUoKTtcblxuICAgICAgICAgICAgdGhpcy5vZmYoJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5vZmYoJ3BpdGNoJywgdGhpcy5zdHlsZS5fcmVkb1BsYWNlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN0eWxlKSB7XG4gICAgICAgICAgICB0aGlzLnN0eWxlID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2UgaWYgKHN0eWxlIGluc3RhbmNlb2YgU3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBuZXcgU3R5bGUoc3R5bGUsIHRoaXMuYW5pbWF0aW9uTG9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0eWxlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9vblN0eWxlTG9hZClcbiAgICAgICAgICAgIC5vbignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdGhpcy5fb25TdHlsZUNoYW5nZSlcbiAgICAgICAgICAgIC5vbignc291cmNlLmFkZCcsIHRoaXMuX29uU291cmNlQWRkKVxuICAgICAgICAgICAgLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5sb2FkJywgdGhpcy5fb25Tb3VyY2VVcGRhdGUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgLm9uKCdsYXllci5hZGQnLCB0aGlzLl9mb3J3YXJkTGF5ZXJFdmVudClcbiAgICAgICAgICAgIC5vbignbGF5ZXIucmVtb3ZlJywgdGhpcy5fZm9yd2FyZExheWVyRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCd0aWxlLmxvYWQnLCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpO1xuXG4gICAgICAgIHRoaXMub24oJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICB0aGlzLm9uKCdwaXRjaCcsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBzb3VyY2UgdG8gdGhlIG1hcCBzdHlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJRCBvZiB0aGUgc291cmNlLiBNdXN0IG5vdCBiZSB1c2VkIGJ5IGFueSBleGlzdGluZyBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBzb3VyY2Ugc3BlY2lmaWNhdGlvbiwgZm9sbG93aW5nIHRoZVxuICAgICAqIFtNYXBib3ggR0wgU3R5bGUgUmVmZXJlbmNlXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNzb3VyY2VzKVxuICAgICAqIEBmaXJlcyBzb3VyY2UuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkU291cmNlOiBmdW5jdGlvbihpZCwgc291cmNlKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuYWRkU291cmNlKGlkLCBzb3VyY2UpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFuIGV4aXN0aW5nIHNvdXJjZSBmcm9tIHRoZSBtYXAgc3R5bGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSUQgb2YgdGhlIHNvdXJjZSB0byByZW1vdmVcbiAgICAgKiBAZmlyZXMgc291cmNlLnJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZVNvdXJjZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5yZW1vdmVTb3VyY2UoaWQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBzdHlsZSBzb3VyY2Ugb2JqZWN0IHdpdGggdGhlIGdpdmVuIGBpZGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgc291cmNlIElEXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRTb3VyY2U6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFNvdXJjZShpZCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGxheWVyIHRvIHRoZSBtYXAgc3R5bGUuIFRoZSBsYXllciB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGUgbGF5ZXIgd2l0aFxuICAgICAqIElEIGBiZWZvcmVgLCBvciBhcHBlbmRlZCBpZiBgYmVmb3JlYCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7U3R5bGVMYXllcnxPYmplY3R9IGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSBiZWZvcmUgIElEIG9mIGFuIGV4aXN0aW5nIGxheWVyIHRvIGluc2VydCBiZWZvcmVcbiAgICAgKiBAZmlyZXMgbGF5ZXIuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkTGF5ZXI6IGZ1bmN0aW9uKGxheWVyLCBiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5hZGRMYXllcihsYXllciwgYmVmb3JlKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gYGlkYCBmcm9tIHRoZSBtYXAuIEFueSBsYXllcnMgd2hpY2ggcmVmZXIgdG8gdGhlXG4gICAgICogc3BlY2lmaWVkIGxheWVyIHZpYSBhIGByZWZgIHByb3BlcnR5IGFyZSBhbHNvIHJlbW92ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgbGF5ZXIgaWRcbiAgICAgKiBAZmlyZXMgbGF5ZXIucmVtb3ZlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZUxheWVyOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB0aGlzLnN0eWxlLnJlbW92ZUxheWVyKGlkKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZmlsdGVyIGZvciBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXIgZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0RmlsdGVyOiBmdW5jdGlvbihsYXllciwgZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuc2V0RmlsdGVyKGxheWVyLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBmaWx0ZXIgZm9yIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICovXG4gICAgZ2V0RmlsdGVyOiBmdW5jdGlvbihsYXllcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHlsZS5nZXRGaWx0ZXIobGF5ZXIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHZhbHVlIG9mIGEgcGFpbnQgcHJvcGVydHkgaW4gYSBnaXZlbiBzdHlsZSBsYXllci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYXllciBJRCBvZiBhIGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgbmFtZSBvZiBhIHBhaW50IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIHBhaW50IHByb3Blcnk7IG11c3QgaGF2ZSB0aGUgdHlwZSBhcHByb3ByaWF0ZSBmb3IgdGhlIHByb3BlcnR5IGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB0aGlzLnN0eWxlLnNldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcyk7XG4gICAgICAgIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMudXBkYXRlKHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB2YWx1ZSBvZiBhIHBhaW50IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBwYWludCBwcm9wZXJ0eVxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0ga2xhc3Mgb3B0aW9uYWwgY2xhc3Mgc3BlY2lmaWVyIGZvciB0aGUgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdmFsdWUgZm9yIHRoZSBwYWludCBwcm9wZXJ5XG4gICAgICovXG4gICAgZ2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIGtsYXNzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIGtsYXNzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB2YWx1ZSBvZiBhIGxheW91dCBwcm9wZXJ0eSBpbiBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIGEgbGF5b3V0IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIGxheW91dCBwcm9wZXJ5OyBtdXN0IGhhdmUgdGhlIHR5cGUgYXBwcm9wcmlhdGUgZm9yIHRoZSBwcm9wZXJ0eSBhcyBkZWZpbmVkIGluIHRoZSBbU3R5bGUgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXBib3gtZ2wtc3R5bGUtc3BlYy8pXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnN0eWxlLnNldExheW91dFByb3BlcnR5KGxheWVyLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHZhbHVlIG9mIGEgbGF5b3V0IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMgeyp9IHZhbHVlIGZvciB0aGUgbGF5b3V0IHByb3BlcnlcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGF5b3V0UHJvcGVydHkobGF5ZXIsIG5hbWUpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIE1hcCdzIGNvbnRhaW5lciBhcyBhbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGFpbmVyIGZvciB0aGUgbWFwIGBjYW52YXNgIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBhZGQgbm9uLUdMIG92ZXJsYXlzIHRvIHRoZSBtYXAsIHlvdSBzaG91bGQgYXBwZW5kIHRoZW0gdG8gdGhpcyBlbGVtZW50LiBUaGlzXG4gICAgICogaXMgdGhlIGVsZW1lbnQgdG8gd2hpY2ggZXZlbnQgYmluZGluZ3MgZm9yIG1hcCBpbnRlcmFjdGl2aXR5IHN1Y2ggYXMgcGFubmluZyBhbmQgem9vbWluZyBhcmVcbiAgICAgKiBhdHRhY2hlZC4gSXQgd2lsbCByZWNlaXZlIGJ1YmJsZWQgZXZlbnRzIGZvciBjaGlsZCBlbGVtZW50cyBzdWNoIGFzIHRoZSBgY2FudmFzYCwgYnV0IG5vdCBmb3JcbiAgICAgKiBtYXAgY29udHJvbHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENhbnZhc0NvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYW52YXNDb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgTWFwJ3MgY2FudmFzIGFzIGFuIEhUTUwgY2FudmFzXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fSBjYW52YXNcbiAgICAgKi9cbiAgICBnZXRDYW52YXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FudmFzLmdldEVsZW1lbnQoKTtcbiAgICB9LFxuXG4gICAgX3NldHVwQ29udGFpbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGlkID0gdGhpcy5vcHRpb25zLmNvbnRhaW5lcjtcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xuICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtbWFwJyk7XG5cbiAgICAgICAgdmFyIGNhbnZhc0NvbnRhaW5lciA9IHRoaXMuX2NhbnZhc0NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jYW52YXMtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgY2FudmFzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWludGVyYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2FudmFzID0gbmV3IENhbnZhcyh0aGlzLCBjYW52YXNDb250YWluZXIpO1xuXG4gICAgICAgIHZhciBjb250cm9sQ29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWNvbnRyb2wtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgdmFyIGNvcm5lcnMgPSB0aGlzLl9jb250cm9sQ29ybmVycyA9IHt9O1xuICAgICAgICBbJ3RvcC1sZWZ0JywgJ3RvcC1yaWdodCcsICdib3R0b20tbGVmdCcsICdib3R0b20tcmlnaHQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIGNvcm5lcnNbcG9zXSA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jdHJsLScgKyBwb3MsIGNvbnRyb2xDb250YWluZXIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgX3NldHVwUGFpbnRlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnbCA9IHRoaXMuX2NhbnZhcy5nZXRXZWJHTENvbnRleHQoe1xuICAgICAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogdGhpcy5vcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQsXG4gICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRoaXMub3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXJcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFnbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0wnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFpbnRlciA9IG5ldyBQYWludGVyKGdsLCB0aGlzLnRyYW5zZm9ybSk7XG4gICAgfSxcblxuICAgIF9jb250ZXh0TG9zdDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIGJyb3dzZXIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRleHRSZXN0b3JlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJcyB0aGlzIG1hcCBmdWxseSBsb2FkZWQ/IElmIHRoZSBzdHlsZSBpc24ndCBsb2FkZWRcbiAgICAgKiBvciBpdCBoYXMgYSBjaGFuZ2UgdG8gdGhlIHNvdXJjZXMgb3Igc3R5bGUgdGhhdCBpc24ndFxuICAgICAqIHByb3BhZ2F0ZWQgdG8gaXRzIHN0eWxlLCByZXR1cm4gZmFsc2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gd2hldGhlciB0aGUgbWFwIGlzIGxvYWRlZFxuICAgICAqL1xuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHlsZURpcnR5IHx8IHRoaXMuX3NvdXJjZXNEaXJ0eSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUgJiYgIXRoaXMuc3R5bGUubG9hZGVkKCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhpcyBtYXAncyBzdHlsZSBhbmQgcmUtcmVuZGVyIHRoZSBtYXAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdXBkYXRlU3R5bGUgbmV3IHN0eWxlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXBkYXRlU3R5bGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0eWxlKSByZXR1cm4gdGhpcztcblxuICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gdGhpcy5fc3R5bGVEaXJ0eSB8fCB1cGRhdGVTdHlsZTtcbiAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHdoZW4gYSAocmUtKXJlbmRlciBvZiB0aGUgbWFwIGlzIHJlcXVpcmVkLCBlLmcuIHdoZW4gdGhlXG4gICAgICogdXNlciBwYW5uZWQgb3Igem9vbWVkLGYgb3IgbmV3IGRhdGEgaXMgYXZhaWxhYmxlLlxuICAgICAqIEByZXR1cm5zIHtNYXB9IHRoaXNcbiAgICAgKi9cbiAgICByZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiB0aGlzLl9zdHlsZURpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnN0eWxlLl9yZWNhbGN1bGF0ZSh0aGlzLnRyYW5zZm9ybS56b29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnN0eWxlICYmIHRoaXMuX3NvdXJjZXNEaXJ0eSAmJiAhdGhpcy5fc291cmNlc0RpcnR5VGltZW91dCkge1xuICAgICAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSwgNTApO1xuICAgICAgICAgICAgdGhpcy5zdHlsZS5fdXBkYXRlU291cmNlcyh0aGlzLnRyYW5zZm9ybSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhaW50ZXIucmVuZGVyKHRoaXMuc3R5bGUsIHtcbiAgICAgICAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxuICAgICAgICAgICAgdmVydGljZXM6IHRoaXMudmVydGljZXMsXG4gICAgICAgICAgICByb3RhdGluZzogdGhpcy5yb3RhdGluZyxcbiAgICAgICAgICAgIHpvb21pbmc6IHRoaXMuem9vbWluZ1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmZpcmUoJ3JlbmRlcicpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRlZCgpICYmICF0aGlzLl9sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2ZyYW1lSWQgPSBudWxsO1xuXG4gICAgICAgIGlmICghdGhpcy5hbmltYXRpb25Mb29wLnN0b3BwZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fc291cmNlc0RpcnR5IHx8IHRoaXMuX3JlcGFpbnQgfHwgIXRoaXMuYW5pbWF0aW9uTG9vcC5zdG9wcGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRGVzdHJveXMgdGhlIG1hcCdzIHVuZGVybHlpbmcgcmVzb3VyY2VzLCBpbmNsdWRpbmcgd2ViIHdvcmtlcnMuXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYXNoKSB0aGlzLl9oYXNoLnJlbW92ZSgpO1xuICAgICAgICBicm93c2VyLmNhbmNlbEZyYW1lKHRoaXMuX2ZyYW1lSWQpO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fc291cmNlc0RpcnR5VGltZW91dCk7XG4gICAgICAgIHRoaXMuc2V0U3R5bGUobnVsbCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcmVyZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiAhdGhpcy5fZnJhbWVJZCkge1xuICAgICAgICAgICAgdGhpcy5fZnJhbWVJZCA9IGJyb3dzZXIuZnJhbWUodGhpcy5yZW5kZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU3R5bGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3N0eWxlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU291cmNlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy5maXJlKGUudHlwZSwgdXRpbC5leHRlbmQoe3N0eWxlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgX2ZvcndhcmRMYXllckV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkVGlsZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9vblN0eWxlTG9hZDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLnN0eWxlLl9jYXNjYWRlKHRoaXMuX2NsYXNzZXMsIHt0cmFuc2l0aW9uOiBmYWxzZX0pO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU3R5bGVDaGFuZ2U6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGUodHJ1ZSk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTdHlsZUV2ZW50KGUpO1xuICAgIH0sXG5cbiAgICBfb25Tb3VyY2VBZGQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGUuc291cmNlO1xuICAgICAgICBpZiAoc291cmNlLm9uQWRkKVxuICAgICAgICAgICAgc291cmNlLm9uQWRkKHRoaXMpO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQoZSk7XG4gICAgfSxcblxuICAgIF9vblNvdXJjZVJlbW92ZTogZnVuY3Rpb24oZSkge1xuICAgICAgICB2YXIgc291cmNlID0gZS5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2Uub25SZW1vdmUpXG4gICAgICAgICAgICBzb3VyY2Uub25SZW1vdmUodGhpcyk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU291cmNlVXBkYXRlOiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9XG59KTtcblxudXRpbC5leHRlbmRBbGwoTWFwLnByb3RvdHlwZSwge1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlIGRlYnVnZ2luZyBtb2RlXG4gICAgICpcbiAgICAgKiBAbmFtZSBkZWJ1Z1xuICAgICAqIEBtZW1iZXJvZiBNYXBcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfZGVidWc6IGZhbHNlLFxuICAgIGdldCBkZWJ1ZygpIHsgcmV0dXJuIHRoaXMuX2RlYnVnOyB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkgeyB0aGlzLl9kZWJ1ZyA9IHZhbHVlOyB0aGlzLnVwZGF0ZSgpOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2hvdyBjb2xsaXNpb24gYm94ZXM6IHVzZWZ1bCBmb3IgZGVidWdnaW5nIGxhYmVsIHBsYWNlbWVudFxuICAgICAqIGluIHN0eWxlcy5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbGxpc2lvbkRlYnVnXG4gICAgICogQG1lbWJlcm9mIE1hcFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIF9jb2xsaXNpb25EZWJ1ZzogZmFsc2UsXG4gICAgZ2V0IGNvbGxpc2lvbkRlYnVnKCkgeyByZXR1cm4gdGhpcy5fY29sbGlzaW9uRGVidWc7IH0sXG4gICAgc2V0IGNvbGxpc2lvbkRlYnVnKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbGxpc2lvbkRlYnVnID0gdmFsdWU7XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHlsZS5zb3VyY2VzW2ldLnJlbG9hZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3R5bGUuc291cmNlc1tpXS5yZWxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBFbmFibGUgY29udGludW91cyByZXBhaW50IHRvIGFuYWx5emUgcGVyZm9ybWFuY2VcbiAgICAgKlxuICAgICAqIEBuYW1lIHJlcGFpbnRcbiAgICAgKiBAbWVtYmVyb2YgTWFwXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3JlcGFpbnQ6IGZhbHNlLFxuICAgIGdldCByZXBhaW50KCkgeyByZXR1cm4gdGhpcy5fcmVwYWludDsgfSxcbiAgICBzZXQgcmVwYWludCh2YWx1ZSkgeyB0aGlzLl9yZXBhaW50ID0gdmFsdWU7IHRoaXMudXBkYXRlKCk7IH0sXG5cbiAgICAvLyBzaG93IHZlcnRpY2VzXG4gICAgX3ZlcnRpY2VzOiBmYWxzZSxcbiAgICBnZXQgdmVydGljZXMoKSB7IHJldHVybiB0aGlzLl92ZXJ0aWNlczsgfSxcbiAgICBzZXQgdmVydGljZXModmFsdWUpIHsgdGhpcy5fdmVydGljZXMgPSB2YWx1ZTsgdGhpcy51cGRhdGUoKTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9wdXA7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgcG9wdXAgY29tcG9uZW50XG4gKiBAY2xhc3MgUG9wdXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuY2xvc2VCdXR0b25cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gb3B0aW9ucy5jbG9zZU9uQ2xpY2tcbiAqIEBleGFtcGxlXG4gKiB2YXIgdG9vbHRpcCA9IG5ldyBtYXBib3hnbC5Qb3B1cCgpXG4gKiAgIC5zZXRMYXRMbmcobWFwLnVucHJvamVjdChlLnBvaW50KSlcbiAqICAgLnNldEhUTUwoXCI8aDE+SGVsbG8gV29ybGQhPC9oMT5cIilcbiAqICAgLmFkZFRvKG1hcCk7XG4gKi9cbmZ1bmN0aW9uIFBvcHVwKG9wdGlvbnMpIHtcbiAgICB1dGlsLnNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ191cGRhdGVQb3NpdGlvbicsXG4gICAgICAgICdfb25DbGlja0Nsb3NlJ10sXG4gICAgICAgIHRoaXMpO1xufVxuXG5Qb3B1cC5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwgLyoqIEBsZW5kcyBQb3B1cC5wcm90b3R5cGUgKi97XG4gICAgb3B0aW9uczoge1xuICAgICAgICBjbG9zZUJ1dHRvbjogdHJ1ZSxcbiAgICAgICAgY2xvc2VPbkNsaWNrOiB0cnVlXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIHRoZSBwb3B1cCB0byBhIG1hcFxuICAgICAqIEBwYXJhbSB7TWFwfSBtYXBcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmUnLCB0aGlzLl91cGRhdGVQb3NpdGlvbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5fb25DbGlja0Nsb3NlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHBvcHVwIGZyb20gdGhlIG1hcFxuICAgICAqIEBleGFtcGxlXG4gICAgICogdmFyIHBvcHVwID0gbmV3IG1hcGJveGdsLlBvcHVwKCkuYWRkVG8obWFwKTtcbiAgICAgKiBwb3B1cC5yZW1vdmUoKTtcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbWFwKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlJywgdGhpcy5fdXBkYXRlUG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy5fbWFwLm9mZignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX21hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgY29vcmRpbmF0ZXMgb2YgcG9wdXAgZWxlbWVudCByZWxhdGl2ZSB0byBtYXBcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfVxuICAgICAqL1xuICAgIGdldExhdExuZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYXRMbmc7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY29vcmRpbmF0ZXMgb2YgYSBwb3B1cCBlbGVtZW50IHRvIGEgbWFwXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtQb3B1cH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF0TG5nOiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdGhpcy5fbGF0TG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIHRleHQgb25seSBjb250ZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHNldFRleHQ6IGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgdGhpcy5fY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIEhUTUwgY29udGVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRIVE1MOiBmdW5jdGlvbihodG1sKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgICAgICAgdmFyIHRlbXAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib2R5JyksIGNoaWxkO1xuICAgICAgICB0ZW1wLmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjaGlsZCA9IHRlbXAuZmlyc3RDaGlsZDtcbiAgICAgICAgICAgIGlmICghY2hpbGQpIGJyZWFrO1xuICAgICAgICAgICAgdGhpcy5fY29udGVudC5hcHBlbmRDaGlsZChjaGlsZCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1wb3B1cCcsIHRoaXMuX21hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgICAgIHRoaXMuX3RpcCAgICAgPSBET00uY3JlYXRlKCdkaXYnLCAnbWFwYm94Z2wtcG9wdXAtdGlwJywgICAgIHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgICAgICB0aGlzLl93cmFwcGVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLXBvcHVwLWNvbnRlbnQnLCB0aGlzLl9jb250YWluZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNsb3NlQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24gPSBET00uY3JlYXRlKCdidXR0b24nLCAnbWFwYm94Z2wtcG9wdXAtY2xvc2UtYnV0dG9uJywgdGhpcy5fd3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uaW5uZXJIVE1MID0gJyYjMjE1Oyc7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGVudCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlQ29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fY29udGVudCB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fd3JhcHBlcjtcblxuICAgICAgICB3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICAgICAgICAgIG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGhpcy5fY2xvc2VCdXR0b24pO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2xhdExuZyB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBwb3MgPSB0aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sYXRMbmcpLnJvdW5kKCksXG4gICAgICAgICAgICBhbmNob3IgPSB0aGlzLm9wdGlvbnMuYW5jaG9yO1xuXG4gICAgICAgIGlmICghYW5jaG9yKSB7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgaWYgKHBvcy55IDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gWyd0b3AnXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9zLnkgPiB0aGlzLl9tYXAudHJhbnNmb3JtLmhlaWdodCAtIGhlaWdodCkge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFsnYm90dG9tJ107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocG9zLnggPCB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgnbGVmdCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwb3MueCA+IHRoaXMuX21hcC50cmFuc2Zvcm0ud2lkdGggLSB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgncmlnaHQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFuY2hvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBhbmNob3IgPSAnYm90dG9tJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gYW5jaG9yLmpvaW4oJy0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFuY2hvciA9IGFuY2hvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhbmNob3JUcmFuc2xhdGUgPSB7XG4gICAgICAgICAgICAndG9wJzogJ3RyYW5zbGF0ZSgtNTAlLDApJyxcbiAgICAgICAgICAgICd0b3AtbGVmdCc6ICd0cmFuc2xhdGUoMCwwKScsXG4gICAgICAgICAgICAndG9wLXJpZ2h0JzogJ3RyYW5zbGF0ZSgtMTAwJSwwKScsXG4gICAgICAgICAgICAnYm90dG9tJzogJ3RyYW5zbGF0ZSgtNTAlLC0xMDAlKScsXG4gICAgICAgICAgICAnYm90dG9tLWxlZnQnOiAndHJhbnNsYXRlKDAsLTEwMCUpJyxcbiAgICAgICAgICAgICdib3R0b20tcmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC0xMDAlKScsXG4gICAgICAgICAgICAnbGVmdCc6ICd0cmFuc2xhdGUoMCwtNTAlKScsXG4gICAgICAgICAgICAncmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC01MCUpJ1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0O1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gYW5jaG9yVHJhbnNsYXRlKSB7XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1wb3B1cC1hbmNob3ItJyArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtcG9wdXAtYW5jaG9yLScgKyBhbmNob3IpO1xuXG4gICAgICAgIERPTS5zZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCBhbmNob3JUcmFuc2xhdGVbYW5jaG9yXSArICcgdHJhbnNsYXRlKCcgKyBwb3MueCArICdweCwnICsgcG9zLnkgKyAncHgpJyk7XG4gICAgfSxcblxuICAgIF9vbkNsaWNrQ2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFjdG9yO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHRoZSBbQWN0b3IgZGVzaWduIHBhdHRlcm5dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWN0b3JfbW9kZWwpXG4gKiB0aGF0IG1haW50YWlucyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYXN5bmNocm9ub3VzIHRhc2tzIGFuZCB0aGUgb2JqZWN0c1xuICogdGhhdCBzcGluIHRoZW0gb2ZmIC0gaW4gdGhpcyBjYXNlLCB0YXNrcyBsaWtlIHBhcnNpbmcgcGFydHMgb2Ygc3R5bGVzLFxuICogb3duZWQgYnkgdGhlIHN0eWxlc1xuICpcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSB0YXJnZXRcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSBwYXJlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEFjdG9yKHRhcmdldCwgcGFyZW50KSB7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5jYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLmNhbGxiYWNrSUQgPSAwO1xuICAgIHRoaXMucmVjZWl2ZSA9IHRoaXMucmVjZWl2ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0aGlzLnJlY2VpdmUsIGZhbHNlKTtcbn1cblxuQWN0b3IucHJvdG90eXBlLnJlY2VpdmUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG4gICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGEsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJzxyZXNwb25zZT4nKSB7XG4gICAgICAgIGNhbGxiYWNrID0gdGhpcy5jYWxsYmFja3NbZGF0YS5pZF07XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tkYXRhLmlkXTtcbiAgICAgICAgY2FsbGJhY2soZGF0YS5lcnJvciB8fCBudWxsLCBkYXRhLmRhdGEpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEuaWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBpZCA9IGRhdGEuaWQ7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhLCBmdW5jdGlvbihlcnIsIGRhdGEsIGJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIHRoaXMucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICc8cmVzcG9uc2U+JyxcbiAgICAgICAgICAgICAgICBpZDogU3RyaW5nKGlkKSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID8gU3RyaW5nKGVycikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGFcbiAgICAgICAgICAgIH0sIGJ1ZmZlcnMpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhKTtcbiAgICB9XG59O1xuXG5BY3Rvci5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCBidWZmZXJzKSB7XG4gICAgdmFyIGlkID0gbnVsbDtcbiAgICBpZiAoY2FsbGJhY2spIHRoaXMuY2FsbGJhY2tzW2lkID0gdGhpcy5jYWxsYmFja0lEKytdID0gY2FsbGJhY2s7XG4gICAgdGhpcy5wb3N0TWVzc2FnZSh7IHR5cGU6IHR5cGUsIGlkOiBTdHJpbmcoaWQpLCBkYXRhOiBkYXRhIH0sIGJ1ZmZlcnMpO1xufTtcblxuLyoqXG4gKiBXcmFwcGVkIHBvc3RNZXNzYWdlIEFQSSB0aGF0IGFic3RyYWN0cyBhcm91bmQgSUUncyBsYWNrIG9mXG4gKiBgdHJhbnNmZXJMaXN0YCBzdXBwb3J0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmZXJMaXN0XG4gKi9cbkFjdG9yLnByb3RvdHlwZS5wb3N0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCkge1xuICAgIHRyeSB7XG4gICAgICAgIHRoaXMudGFyZ2V0LnBvc3RNZXNzYWdlKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLnRhcmdldC5wb3N0TWVzc2FnZShtZXNzYWdlKTsgLy8gTm8gc3VwcG9ydCBmb3IgdHJhbnNmZXJMaXN0IG9uIElFXG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5nZXRKU09OID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTtcbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgY2FsbGJhY2soZSk7XG4gICAgfTtcbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh4aHIuc3RhdHVzID49IDIwMCAmJiB4aHIuc3RhdHVzIDwgMzAwICYmIHhoci5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0QXJyYXlCdWZmZXIgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpO1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oZSkge1xuICAgICAgICBjYWxsYmFjayhlKTtcbiAgICB9O1xuICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCAzMDAgJiYgeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCB4aHIucmVzcG9uc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0SW1hZ2UgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgIGltZy5jcm9zc09yaWdpbiA9ICdBbm9ueW1vdXMnO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgaW1nKTtcbiAgICB9O1xuICAgIGltZy5zcmMgPSB1cmw7XG4gICAgaW1nLmdldERhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBpbWcud2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWcuaGVpZ2h0O1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIDAsIDApO1xuICAgICAgICByZXR1cm4gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW1nLndpZHRoLCBpbWcuaGVpZ2h0KS5kYXRhO1xuICAgIH07XG4gICAgcmV0dXJuIGltZztcbn07XG5cbmV4cG9ydHMuZ2V0VmlkZW8gPSBmdW5jdGlvbih1cmxzLCBjYWxsYmFjaykge1xuICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgdmlkZW8uY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICB2aWRlby5vbmxvYWRzdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCB2aWRlbyk7XG4gICAgfTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzb3VyY2UnKTtcbiAgICAgICAgcy5zcmMgPSB1cmxzW2ldO1xuICAgICAgICB2aWRlby5hcHBlbmRDaGlsZChzKTtcbiAgICB9XG4gICAgdmlkZW8uZ2V0RGF0YSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdmlkZW87IH07XG4gICAgcmV0dXJuIHZpZGVvO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENhbnZhcyA9IHJlcXVpcmUoJy4vY2FudmFzJyk7XG5cbnZhciBmcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5mcmFtZSA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgcmV0dXJuIGZyYW1lKGZuKTtcbn07XG5cbnZhciBjYW5jZWwgPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNDYW5jZWxBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5jYW5jZWxGcmFtZSA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgY2FuY2VsKGlkKTtcbn07XG5cbmV4cG9ydHMudGltZWQgPSBmdW5jdGlvbiAoZm4sIGR1ciwgY3R4KSB7XG4gICAgaWYgKCFkdXIpIHtcbiAgICAgICAgZm4uY2FsbChjdHgsIDEpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYWJvcnQgPSBmYWxzZSxcbiAgICAgICAgc3RhcnQgPSB3aW5kb3cucGVyZm9ybWFuY2UgPyB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdygpO1xuXG4gICAgZnVuY3Rpb24gdGljayhub3cpIHtcbiAgICAgICAgaWYgKGFib3J0KSByZXR1cm47XG4gICAgICAgIGlmICghd2luZG93LnBlcmZvcm1hbmNlKSBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIGlmIChub3cgPj0gc3RhcnQgKyBkdXIpIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAobm93IC0gc3RhcnQpIC8gZHVyKTtcbiAgICAgICAgICAgIGV4cG9ydHMuZnJhbWUodGljayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBleHBvcnRzLmZyYW1lKHRpY2spO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyBhYm9ydCA9IHRydWU7IH07XG59O1xuXG4vKipcbiAqIFRlc3Qgd2hldGhlciB0aGUgYmFzaWMgSmF2YVNjcmlwdCBhbmQgRE9NIGZlYXR1cmVzIHJlcXVpcmVkIGZvciBNYXBib3ggR0wgYXJlIHByZXNlbnQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0PWZhbHNlXSBJZiBgdHJ1ZWAsIG1hcCBjcmVhdGlvbiB3aWxsIGZhaWwgaWYgdGhlIGltcGxlbWVudGF0aW9uIGRldGVybWluZXMgdGhhdCB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGNyZWF0ZWQgV2ViR0wgY29udGV4dCB3b3VsZCBiZSBkcmFtYXRpY2FsbHkgbG93ZXIgdGhhbiBleHBlY3RlZC5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBNYXBib3ggR0wgc2hvdWxkIGJlIGV4cGVjdGVkIHRvIHdvcmssIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cbmV4cG9ydHMuc3VwcG9ydGVkID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gICAgdmFyIHN1cHBvcnRzID0gW1xuXG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7IH0sXG5cbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnOyB9LFxuXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShBcnJheS5wcm90b3R5cGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZXZlcnkgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZmlsdGVyICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2ggJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5tYXAgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc29tZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2UgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucmVkdWNlUmlnaHQgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShGdW5jdGlvbi5wcm90b3R5cGUgJiYgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpICYmXG4gICAgICAgICAgICAgICAgISEoT2JqZWN0LmtleXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmNyZWF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmlzU2VhbGVkICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5pc0Zyb3plbiAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuaXNFeHRlbnNpYmxlICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5zZWFsICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAnSlNPTicgaW4gd2luZG93ICYmICdwYXJzZScgaW4gSlNPTiAmJiAnc3RyaW5naWZ5JyBpbiBKU09OO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDYW52YXMoKS5zdXBwb3J0c1dlYkdMQ29udGV4dCgob3B0aW9ucyAmJiBvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpIHx8IGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuICdXb3JrZXInIGluIHdpbmRvdzsgfVxuICAgIF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1cHBvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghc3VwcG9ydHNbaV0oKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydHMuaGFyZHdhcmVDb25jdXJyZW5jeSA9IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5IHx8IDg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGV2aWNlUGl4ZWxSYXRpbycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYW52YXM7XG5cbmZ1bmN0aW9uIENhbnZhcyhwYXJlbnQsIGNvbnRhaW5lcikge1xuICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG5cbiAgICBpZiAocGFyZW50ICYmIGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgIHRoaXMuY2FudmFzLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWNhbnZhcycpO1xuICAgICAgICB0aGlzLmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgcGFyZW50Ll9jb250ZXh0TG9zdC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0cmVzdG9yZWQnLCBwYXJlbnQuX2NvbnRleHRSZXN0b3JlZC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIDApO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgIH1cbn1cblxuQ2FudmFzLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgLy8gUmVxdWVzdCB0aGUgcmVxdWlyZWQgY2FudmFzIHNpemUgdGFraW5nIHRoZSBwaXhlbHJhdGlvIGludG8gYWNjb3VudC5cbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHBpeGVsUmF0aW8gKiB3aWR0aDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBwaXhlbFJhdGlvICogaGVpZ2h0O1xuXG4gICAgLy8gTWFpbnRhaW4gdGhlIHNhbWUgY2FudmFzIHNpemUsIHBvdGVudGlhbGx5IGRvd25zY2FsaW5nIGl0IGZvciBIaURQSSBkaXNwbGF5c1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG59O1xuXG52YXIgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyA9IHtcbiAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgIGFscGhhOiB0cnVlLFxuICAgIHN0ZW5jaWw6IHRydWUsXG4gICAgZGVwdGg6IGZhbHNlXG59O1xuXG5DYW52YXMucHJvdG90eXBlLmdldFdlYkdMQ29udGV4dCA9IGZ1bmN0aW9uKGF0dHJpYnV0ZXMpIHtcbiAgICBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe30sIGF0dHJpYnV0ZXMsIHJlcXVpcmVkQ29udGV4dEF0dHJpYnV0ZXMpO1xuXG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldENvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG59O1xuXG5DYW52YXMucHJvdG90eXBlLnN1cHBvcnRzV2ViR0xDb250ZXh0ID0gZnVuY3Rpb24oZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe1xuICAgICAgICBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0OiBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0XG4gICAgfSwgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyk7XG5cbiAgICBpZiAoJ3Byb2JhYmx5U3VwcG9ydHNDb250ZXh0JyBpbiB0aGlzLmNhbnZhcykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXMucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0KCdleHBlcmltZW50YWwtd2ViZ2wnLCBhdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2UgaWYgKCdzdXBwb3J0c0NvbnRleHQnIGluIHRoaXMuY2FudmFzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhcy5zdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN1cHBvcnRzQ29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhd2luZG93LldlYkdMUmVuZGVyaW5nQ29udGV4dCAmJiAhIXRoaXMuZ2V0V2ViR0xDb250ZXh0KGZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpO1xufTtcblxuQ2FudmFzLnByb3RvdHlwZS5nZXRFbGVtZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFjdG9yID0gcmVxdWlyZSgnLi4vYWN0b3InKTtcbnZhciBXZWJXb3JraWZ5ID0gcmVxdWlyZSgnd2Vid29ya2lmeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERpc3BhdGNoZXI7XG5cbmZ1bmN0aW9uIERpc3BhdGNoZXIobGVuZ3RoLCBwYXJlbnQpIHtcbiAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIHRoaXMuY3VycmVudEFjdG9yID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB3b3JrZXIgPSBuZXcgV2ViV29ya2lmeShyZXF1aXJlKCcuLi8uLi9zb3VyY2Uvd29ya2VyJykpO1xuICAgICAgICB2YXIgYWN0b3IgPSBuZXcgQWN0b3Iod29ya2VyLCBwYXJlbnQpO1xuICAgICAgICBhY3Rvci5uYW1lID0gXCJXb3JrZXIgXCIgKyBpO1xuICAgICAgICB0aGlzLmFjdG9ycy5wdXNoKGFjdG9yKTtcbiAgICB9XG59XG5cbkRpc3BhdGNoZXIucHJvdG90eXBlID0ge1xuICAgIGJyb2FkY2FzdDogZnVuY3Rpb24odHlwZSwgZGF0YSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmFjdG9yc1tpXS5zZW5kKHR5cGUsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNlbmQ6IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCB0YXJnZXRJRCwgYnVmZmVycykge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldElEICE9PSAnbnVtYmVyJyB8fCBpc05hTih0YXJnZXRJRCkpIHtcbiAgICAgICAgICAgIC8vIFVzZSByb3VuZCByb2JpbiB0byBzZW5kIHJlcXVlc3RzIHRvIHdlYiB3b3JrZXJzLlxuICAgICAgICAgICAgdGFyZ2V0SUQgPSB0aGlzLmN1cnJlbnRBY3RvciA9ICh0aGlzLmN1cnJlbnRBY3RvciArIDEpICUgdGhpcy5hY3RvcnMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hY3RvcnNbdGFyZ2V0SURdLnNlbmQodHlwZSwgZGF0YSwgY2FsbGJhY2ssIGJ1ZmZlcnMpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0SUQ7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuYWN0b3JzW2ldLnRhcmdldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24gKHRhZ05hbWUsIGNsYXNzTmFtZSwgY29udGFpbmVyKSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlbC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgaWYgKGNvbnRhaW5lcikgY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcbiAgICByZXR1cm4gZWw7XG59O1xuXG52YXIgZG9jU3R5bGUgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU7XG5cbmZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocHJvcHNbaV0gaW4gZG9jU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBwcm9wc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxudmFyIHNlbGVjdFByb3AgPSB0ZXN0UHJvcChbJ3VzZXJTZWxlY3QnLCAnTW96VXNlclNlbGVjdCcsICdXZWJraXRVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKSxcbiAgICB1c2VyU2VsZWN0O1xuZXhwb3J0cy5kaXNhYmxlRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc2VsZWN0UHJvcCkge1xuICAgICAgICB1c2VyU2VsZWN0ID0gZG9jU3R5bGVbc2VsZWN0UHJvcF07XG4gICAgICAgIGRvY1N0eWxlW3NlbGVjdFByb3BdID0gJ25vbmUnO1xuICAgIH1cbn07XG5leHBvcnRzLmVuYWJsZURyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGVjdFByb3ApIHtcbiAgICAgICAgZG9jU3R5bGVbc2VsZWN0UHJvcF0gPSB1c2VyU2VsZWN0O1xuICAgIH1cbn07XG5cbnZhciB0cmFuc2Zvcm1Qcm9wID0gdGVzdFByb3AoWyd0cmFuc2Zvcm0nLCAnV2Via2l0VHJhbnNmb3JtJ10pO1xuZXhwb3J0cy5zZXRUcmFuc2Zvcm0gPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBlbC5zdHlsZVt0cmFuc2Zvcm1Qcm9wXSA9IHZhbHVlO1xufTtcblxuLy8gU3VwcHJlc3MgdGhlIG5leHQgY2xpY2ssIGJ1dCBvbmx5IGlmIGl0J3MgaW1tZWRpYXRlLlxuZnVuY3Rpb24gc3VwcHJlc3NDbGljayhlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG59XG5leHBvcnRzLnN1cHByZXNzQ2xpY2sgPSBmdW5jdGlvbigpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzdXBwcmVzc0NsaWNrLCB0cnVlKTtcbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG4gICAgfSwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIVFRQX1VSTDogJ2h0dHA6Ly9hLnRpbGVzLm1hcGJveC5jb20nLFxuICAgIEhUVFBTX1VSTDogJ2h0dHBzOi8vYS50aWxlcy5tYXBib3guY29tJyxcbiAgICBGT1JDRV9IVFRQUzogdHJ1ZSxcbiAgICBSRVFVSVJFX0FDQ0VTU19UT0tFTjogdHJ1ZVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLyoqXG4gKiBNZXRob2RzIG1peGVkIGluIHRvIG90aGVyIGNsYXNzZXMgZm9yIGV2ZW50IGNhcGFiaWxpdGllcy5cbiAqIEBtaXhpbiBFdmVudGVkXG4gKi9cbnZhciBFdmVudGVkID0ge1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGEgc3BlY2lmaWVkIGV2ZW50IHdpdGggYSBsaXN0ZW5lciBmdW5jdGlvbiB0aGUgbGF0dGVyIGdldHMgdGhlIGRhdGEgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCB0byBgZmlyZWAgYW5kIGFkZGl0aW9uYWxseSBgdGFyZ2V0YCBhbmQgYHR5cGVgIHByb3BlcnRpZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbjogZnVuY3Rpb24odHlwZSwgZm4pIHtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSB0aGlzLl9ldmVudHNbdHlwZV0gfHwgW107XG4gICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGZuKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgZXZlbnQgbGlzdGVuZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBbdHlwZV0gRXZlbnQgdHlwZS4gSWYgbm9uZSBpcyBzcGVjaWZpZWQsIHJlbW92ZSBhbGwgbGlzdGVuZXJzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2xpc3RlbmVyXSBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQuIElmIG5vbmUgaXMgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgYXJlIHJlbW92ZWRcbiAgICAgKi9cbiAgICBvZmY6IGZ1bmN0aW9uKHR5cGUsIGZuKSB7XG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgICAgLy8gY2xlYXIgYWxsIGxpc3RlbmVycyBpZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMubGlzdGVucyh0eXBlKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGZuKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gdGhpcy5fZXZlbnRzW3R5cGVdLmluZGV4T2YoZm4pO1xuICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbCBhIGZ1bmN0aW9uIG9uY2Ugd2hlbiBhbiBldmVudCBoYXMgZmlyZWRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uY2Ugd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbmNlOiBmdW5jdGlvbih0eXBlLCBmbikge1xuICAgICAgICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMub2ZmKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICAgICAgZm4uY2FsbCh0aGlzLCBkYXRhKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLm9uKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRmlyZSBldmVudCBvZiBhIGdpdmVuIHN0cmluZyB0eXBlIHdpdGggdGhlIGdpdmVuIGRhdGEgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXZlbnQgbmFtZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV0gT3B0aW9uYWwgZGF0YSBwYXNzZWQgZG93biB0byB0aGUgZXZlbnQgb2JqZWN0XG4gICAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgb2JqZWN0IGxpc3RlbnMgdG8gYW4gZXZlbnQgb2YgYSBwYXJ0aWN1bGFyIHR5cGVcbiAgICAgKi9cbiAgICBmaXJlOiBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBkYXRhID0gdXRpbC5leHRlbmQoe30sIGRhdGEpO1xuICAgICAgICB1dGlsLmV4dGVuZChkYXRhLCB7dHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzfSk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmNhbGwodGhpcywgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYW4gZXZlbnQgaXMgcmVnaXN0ZXJlZCB0byBhIHR5cGVcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBvYmplY3QgbGlzdGVucyB0byBhbiBldmVudCBvZiBhIHBhcnRpY3VsYXIgdHlwZVxuICAgICAqL1xuICAgIGxpc3RlbnM6IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICEhKHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbdHlwZV0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRlZDtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaHM7XG5cbmZ1bmN0aW9uIEdseXBocyhwYmYsIGVuZCkge1xuICAgIHRoaXMuc3RhY2tzID0gcGJmLnJlYWRGaWVsZHMocmVhZEZvbnRzdGFja3MsIFtdLCBlbmQpO1xufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrcyh0YWcsIHN0YWNrcywgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkge1xuICAgICAgICB2YXIgZm9udHN0YWNrID0gcGJmLnJlYWRNZXNzYWdlKHJlYWRGb250c3RhY2ssIHtnbHlwaHM6IHt9fSk7XG4gICAgICAgIHN0YWNrcy5wdXNoKGZvbnRzdGFjayk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrKHRhZywgZm9udHN0YWNrLCBwYmYpIHtcbiAgICBpZiAodGFnID09PSAxKSBmb250c3RhY2submFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSAyKSBmb250c3RhY2sucmFuZ2UgPSBwYmYucmVhZFN0cmluZygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykge1xuICAgICAgICB2YXIgZ2x5cGggPSBwYmYucmVhZE1lc3NhZ2UocmVhZEdseXBoLCB7fSk7XG4gICAgICAgIGZvbnRzdGFjay5nbHlwaHNbZ2x5cGguaWRdID0gZ2x5cGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkR2x5cGgodGFnLCBnbHlwaCwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkgZ2x5cGguaWQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgZ2x5cGguYml0bWFwID0gcGJmLnJlYWRCeXRlcygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykgZ2x5cGgud2lkdGggPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgZ2x5cGguaGVpZ2h0ID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDUpIGdseXBoLmxlZnQgPSBwYmYucmVhZFNWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDYpIGdseXBoLnRvcCA9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNykgZ2x5cGguYWR2YW5jZSA9IHBiZi5yZWFkVmFyaW50KCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGU7XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKGEsIGIsIHQpIHtcbiAgICByZXR1cm4gKGEgKiAoMSAtIHQpKSArIChiICogdCk7XG59XG5cbmludGVycG9sYXRlLm51bWJlciA9IGludGVycG9sYXRlO1xuXG5pbnRlcnBvbGF0ZS52ZWMyID0gZnVuY3Rpb24oZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMV0sIHRvWzFdLCB0KVxuICAgIF07XG59O1xuXG4vKlxuICogSW50ZXJwb2xhdGUgYmV0d2VlbiB0d28gY29sb3JzIGdpdmVuIGFzIDQtZWxlbWVudCBhcnJheXMuXG4gKlxuICogQHBhcmFtIHtDb2xvcn0gZnJvbVxuICogQHBhcmFtIHtDb2xvcn0gdG9cbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gZmFjdG9yIGJldHdlZW4gMCBhbmQgMVxuICogQHJldHVybnMge0NvbG9yfSBpbnRlcnBvbGF0ZWQgY29sb3JcbiAqL1xuaW50ZXJwb2xhdGUuY29sb3IgPSBmdW5jdGlvbihmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMF0sIHRvWzBdLCB0KSxcbiAgICAgICAgaW50ZXJwb2xhdGUoZnJvbVsxXSwgdG9bMV0sIHQpLFxuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzJdLCB0b1syXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bM10sIHRvWzNdLCB0KVxuICAgIF07XG59O1xuXG5pbnRlcnBvbGF0ZS5hcnJheSA9IGZ1bmN0aW9uKGZyb20sIHRvLCB0KSB7XG4gICAgcmV0dXJuIGZyb20ubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlKGQsIHRvW2ldLCB0KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuL2Jyb3dzZXInKTtcblxuZnVuY3Rpb24gbm9ybWFsaXplVVJMKHVybCwgcGF0aFByZWZpeCwgYWNjZXNzVG9rZW4pIHtcbiAgICBhY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuIHx8IGNvbmZpZy5BQ0NFU1NfVE9LRU47XG5cbiAgICBpZiAoIWFjY2Vzc1Rva2VuICYmIGNvbmZpZy5SRVFVSVJFX0FDQ0VTU19UT0tFTikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FuIEFQSSBhY2Nlc3MgdG9rZW4gaXMgcmVxdWlyZWQgdG8gdXNlIE1hcGJveCBHTC4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZGV2ZWxvcGVycy9hcGkvI2FjY2Vzcy10b2tlbnMnKTtcbiAgICB9XG5cbiAgICB2YXIgaHR0cHMgPSBjb25maWcuRk9SQ0VfSFRUUFMgfHxcbiAgICAgICAgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonKTtcblxuICAgIHVybCA9IHVybC5yZXBsYWNlKC9ebWFwYm94OlxcL1xcLy8sIChodHRwcyA/IGNvbmZpZy5IVFRQU19VUkwgOiBjb25maWcuSFRUUF9VUkwpICsgcGF0aFByZWZpeCk7XG4gICAgdXJsICs9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyZhY2Nlc3NfdG9rZW49JyA6ICc/YWNjZXNzX3Rva2VuPSc7XG5cbiAgICBpZiAoY29uZmlnLlJFUVVJUkVfQUNDRVNTX1RPS0VOKSB7XG4gICAgICAgIGlmIChhY2Nlc3NUb2tlblswXSA9PT0gJ3MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VzZSBhIHB1YmxpYyBhY2Nlc3MgdG9rZW4gKHBrLiopIHdpdGggTWFwYm94IEdMIEpTLCBub3QgYSBzZWNyZXQgYWNjZXNzIHRva2VuIChzay4qKS4gJyArXG4gICAgICAgICAgICAgICAgJ1NlZSBodHRwczovL3d3dy5tYXBib3guY29tL2RldmVsb3BlcnMvYXBpLyNhY2Nlc3MtdG9rZW5zJyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cmwgKz0gYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybDtcbn1cblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU3R5bGVVUkwgPSBmdW5jdGlvbih1cmwsIGFjY2Vzc1Rva2VuKSB7XG4gICAgdmFyIHVzZXIgPSB1cmwubWF0Y2goL15tYXBib3g6XFwvXFwvKFteLl0rKS8pO1xuICAgIGlmICghdXNlcilcbiAgICAgICAgcmV0dXJuIHVybDtcblxuICAgIHJldHVybiBub3JtYWxpemVVUkwodXJsLCAnL3N0eWxlcy92MS8nICsgdXNlclsxXSArICcvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU291cmNlVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgdXJsID0gbm9ybWFsaXplVVJMKHVybCArICcuanNvbicsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xuXG4gICAgLy8gVGlsZUpTT04gcmVxdWVzdHMgbmVlZCBhIHNlY3VyZSBmbGFnIGFwcGVuZGVkIHRvIHRoZWlyIFVSTHMgc29cbiAgICAvLyB0aGF0IHRoZSBzZXJ2ZXIga25vd3MgdG8gc2VuZCBTU0wtaWZpZWQgcmVzb3VyY2UgcmVmZXJlbmNlcy5cbiAgICBpZiAodXJsLmluZGV4T2YoJ2h0dHBzJykgPT09IDApXG4gICAgICAgIHVybCArPSAnJnNlY3VyZSc7XG5cbiAgICByZXR1cm4gdXJsO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplR2x5cGhzVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZVVSTCh1cmwsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplVGlsZVVSTCA9IGZ1bmN0aW9uKHVybCwgc291cmNlVXJsKSB7XG4gICAgaWYgKCFzb3VyY2VVcmwgfHwgIXNvdXJjZVVybC5tYXRjaCgvXm1hcGJveDpcXC9cXC8vKSlcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICByZXR1cm4gdXJsLnJlcGxhY2UoL1xcLigoPzpwbmd8anBnKVxcZCopKD89JHxcXD8pLywgYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID49IDIgPyAnQDJ4LiQxJyA6ICcuJDEnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBBIFttb3N0LXJlY2VudGx5LXVzZWQgY2FjaGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FjaGVfYWxnb3JpdGhtcylcbiAqIHdpdGggaGFzaCBsb29rdXAgbWFkZSBwb3NzaWJsZSBieSBrZWVwaW5nIGEgbGlzdCBvZiBrZXlzIGluIHBhcmFsbGVsIHRvXG4gKiBhbiBhcnJheSBvZiBkaWN0aW9uYXJ5IG9mIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXggbnVtYmVyIG9mIHBlcm1pdHRlZCB2YWx1ZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVtb3ZlIGNhbGxiYWNrIGNhbGxlZCB3aXRoIGl0ZW1zIHdoZW4gdGhleSBleHBpcmVcbiAqIEBwcml2YXRlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gTVJVQ2FjaGU7XG5mdW5jdGlvbiBNUlVDYWNoZShtYXgsIG9uUmVtb3ZlKSB7XG4gICAgdGhpcy5tYXggPSBtYXg7XG4gICAgdGhpcy5vblJlbW92ZSA9IG9uUmVtb3ZlO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cblxuLyoqXG4gKiBDbGVhciB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7TVJVQ2FjaGV9IHRoaXMgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMubGlzdCkge1xuICAgICAgICB0aGlzLm9uUmVtb3ZlKHRoaXMubGlzdFtrZXldKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpc3QgPSB7fTtcbiAgICB0aGlzLm9yZGVyID0gW107XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBBZGQgYSBrZXksIHZhbHVlIGNvbWJpbmF0aW9uIHRvIHRoZSBjYWNoZSwgdHJpbW1pbmcgaXRzIHNpemUgaWYgdGhpcyBwdXNoZXNcbiAqIGl0IG92ZXIgbWF4IGxlbmd0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IGxvb2t1cCBrZXkgZm9yIHRoZSBpdGVtXG4gKiBAcGFyYW0geyp9IGRhdGEgYW55IHZhbHVlXG4gKlxuICogQHJldHVybnMge01SVUNhY2hlfSB0aGlzIGNhY2hlXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB0aGlzLmxpc3Rba2V5XSA9IGRhdGE7XG4gICAgdGhpcy5vcmRlci5wdXNoKGtleSk7XG5cbiAgICBpZiAodGhpcy5vcmRlci5sZW5ndGggPiB0aGlzLm1heCkge1xuICAgICAgICB2YXIgcmVtb3ZlZERhdGEgPSB0aGlzLmdldCh0aGlzLm9yZGVyWzBdKTtcbiAgICAgICAgaWYgKHJlbW92ZWREYXRhKSB0aGlzLm9uUmVtb3ZlKHJlbW92ZWREYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYGtleWAgaXMgcHJlc2VudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBiZSBsb29rZWQtdXBcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIHRoZSBjYWNoZSBoYXMgdGhpcyB2YWx1ZVxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmxpc3Q7XG59O1xuXG4vKlxuICogTGlzdCBhbGwga2V5cyBpbiB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gYW4gYXJyYXkgb2Yga2V5cyBpbiB0aGlzIGNhY2hlLlxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm9yZGVyO1xufTtcblxuLypcbiAqIEdldCB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYSBzcGVjaWZpYyBrZXkuIElmIHRoZSBrZXkgaXMgbm90IGZvdW5kLFxuICogcmV0dXJucyBgbnVsbGBcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gbG9vayB1cFxuICogQHJldHVybnMgeyp9IHRoZSBkYXRhLCBvciBudWxsIGlmIGl0IGlzbid0IGZvdW5kXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsgcmV0dXJuIG51bGw7IH1cblxuICAgIHZhciBkYXRhID0gdGhpcy5saXN0W2tleV07XG5cbiAgICBkZWxldGUgdGhpcy5saXN0W2tleV07XG4gICAgdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGtleSksIDEpO1xuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUb2tlbnM7XG5cbi8qKlxuICogUmVwbGFjZSB0b2tlbnMgaW4gYSBzdHJpbmcgdGVtcGxhdGUgd2l0aCB2YWx1ZXMgaW4gYW4gb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgYSBrZXkvdmFsdWUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9rZW5zIGFuZCByZXBsYWNlbWVudHNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IHRoZSB0ZW1wbGF0ZSBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0ZW1wbGF0ZSB3aXRoIHRva2VucyByZXBsYWNlZFxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVRva2Vucyhwcm9wZXJ0aWVzLCB0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgveyhbXnt9KClcXFtcXF08PiQ9OjsuLF5dKyl9L2csIGZ1bmN0aW9uKG1hdGNoLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSBpbiBwcm9wZXJ0aWVzID8gcHJvcGVydGllc1trZXldIDogJyc7XG4gICAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBVbml0QmV6aWVyID0gcmVxdWlyZSgndW5pdGJlemllcicpO1xuXG4vKipcbiAqIEdpdmVuIGEgdmFsdWUgYHRgIHRoYXQgdmFyaWVzIGJldHdlZW4gMCBhbmQgMSwgcmV0dXJuXG4gKiBhbiBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uIHRoYXQgZWFzZXMgYmV0d2VlbiAwIGFuZCAxIGluIGEgcGxlYXNpbmdcbiAqIGN1YmljIGluLW91dCBmYXNoaW9uLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IGlucHV0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBpbnB1dFxuICovXG5leHBvcnRzLmVhc2VDdWJpY0luT3V0ID0gZnVuY3Rpb24gKHQpIHtcbiAgICBpZiAodCA8PSAwKSByZXR1cm4gMDtcbiAgICBpZiAodCA+PSAxKSByZXR1cm4gMTtcbiAgICB2YXIgdDIgPSB0ICogdCxcbiAgICAgICAgdDMgPSB0MiAqIHQ7XG4gICAgcmV0dXJuIDQgKiAodCA8IDAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAwLjc1KTtcbn07XG5cbi8qKlxuICogR2l2ZW4gZ2l2ZW4gKHgsIHkpLCAoeDEsIHkxKSBjb250cm9sIHBvaW50cyBmb3IgYSBiZXppZXIgY3VydmUsXG4gKiByZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGludGVycG9sYXRlcyBhbG9uZyB0aGF0IGN1cnZlLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMXggY29udHJvbCBwb2ludCAxIHggY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHAxeSBjb250cm9sIHBvaW50IDEgeSBjb29yZGluYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gcDJ4IGNvbnRyb2wgcG9pbnQgMiB4IGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMnkgY29udHJvbCBwb2ludCAyIHkgY29vcmRpbmF0ZVxuICogQHJldHVybnMge0Z1bmN0aW9ufSBpbnRlcnBvbGF0b3I6IHJlY2VpdmVzIG51bWJlciB2YWx1ZSwgcmV0dXJuc1xuICogbnVtYmVyIHZhbHVlLlxuICovXG5leHBvcnRzLmJlemllciA9IGZ1bmN0aW9uKHAxeCwgcDF5LCBwMngsIHAyeSkge1xuICAgIHZhciBiZXppZXIgPSBuZXcgVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiBiZXppZXIuc29sdmUodCk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogQSBkZWZhdWx0IGJlemllci1jdXJ2ZSBwb3dlcmVkIGVhc2luZyBmdW5jdGlvbiB3aXRoXG4gKiBjb250cm9sIHBvaW50cyAoMC4yNSwgMC4xKSBhbmQgKDAuMjUsIDEpXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IG91dHB1dFxuICovXG5leHBvcnRzLmVhc2UgPSBleHBvcnRzLmJlemllcigwLjI1LCAwLjEsIDAuMjUsIDEpO1xuXG4vKipcbiAqIEdpdmVuIGEgZm91ci1lbGVtZW50IGFycmF5IG9mIG51bWJlcnMgdGhhdCByZXByZXNlbnRzIGEgY29sb3IgaW5cbiAqIFJHQkEsIHJldHVybiBhIHZlcnNpb24gZm9yIHdoaWNoIHRoZSBSR0IgY29tcG9uZW50cyBhcmUgbXVsdGlwbGllZFxuICogYnkgdGhlIEEgKGFscGhhKSBjb21wb25lbnRcbiAqXG4gKiBAcGFyYW0ge051bWJlcjxBcnJheT59IGMgY29sb3IgYXJyYXlcbiAqIEByZXR1cm5zIHtOdW1iZXI8QXJyYXk+fSBwcmVtdWx0aXBsaWVkIGNvbG9yIGFycmF5XG4gKi9cbmV4cG9ydHMucHJlbXVsdGlwbHkgPSBmdW5jdGlvbiAoYykge1xuICAgIGNbMF0gKj0gY1szXTtcbiAgICBjWzFdICo9IGNbM107XG4gICAgY1syXSAqPSBjWzNdO1xuICAgIHJldHVybiBjO1xufTtcblxuLyoqXG4gKiBjb25zdHJhaW4gbiB0byB0aGUgZ2l2ZW4gcmFuZ2UgdmlhIG1pbiArIG1heFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuIHZhbHVlXG4gKiBAcGFyYW0ge051bWJlcn0gbWluIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4IHRoZSBtYXhpbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcmV0dXJucyB7TnVtYmVyfSB0aGUgY2xhbXBlZCB2YWx1ZVxuICovXG5leHBvcnRzLmNsYW1wID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCBuKSk7XG59O1xuXG4vKlxuICogY29uc3RyYWluIG4gdG8gdGhlIGdpdmVuIHJhbmdlIHZpYSBtb2R1bGFyIGFyaXRobWV0aWNcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcGFyYW0ge051bWJlcn0gbWluXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBjb25zdHJhaW5lZCBudW1iZXJcbiAqL1xuZXhwb3J0cy53cmFwID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgcmV0dXJuIG4gPT09IG1heCA/IG4gOiAoKG4gLSBtaW4pICUgZCArIGQpICUgZCArIG1pbjtcbn07XG5cbi8qXG4gKiByZXR1cm4gdGhlIGZpcnN0IG5vbi1udWxsIGFuZCBub24tdW5kZWZpbmVkIGFyZ3VtZW50IHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7Kn0gYXJndW1lbnRcbiAqL1xuZXhwb3J0cy5jb2FsZXNjZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGlmIChhcmcgIT09IG51bGwgJiYgYXJnICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gYXJnO1xuICAgIH1cbn07XG5cbi8qXG4gKiBDYWxsIGFuIGFzeW5jaHJvbm91cyBmdW5jdGlvbiBvbiBhbiBhcnJheSBvZiBhcmd1bWVudHMsXG4gKiBjYWxsaW5nIGBjYWxsYmFja2Agb25jZSBhbGwgY2FsbHMgY29tcGxldGUuXG4gKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyYXkgaW5wdXQgdG8gZWFjaCBjYWxsIG9mIHRoZSBhc3luYyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIGFuIGFzeW5jIGZ1bmN0aW9uIHdpdGggc2lnbmF0dXJlIChkYXRhLCBjYWxsYmFjaylcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgY2FsbGJhY2sgcnVuIGFmdGVyIGFsbCBhc3luYyB3b3JrIGlzIGRvbmUuXG4gKiBjYWxsZWQgd2l0aCBubyBhcmd1bWVudHNcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydHMuYXN5bmNFYWNoID0gZnVuY3Rpb24gKGFycmF5LCBmbiwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVtYWluaW5nID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChyZW1haW5pbmcgPT09IDApIHJldHVybiBjYWxsYmFjaygpO1xuICAgIGZ1bmN0aW9uIGNoZWNrKCkgeyBpZiAoLS1yZW1haW5pbmcgPT09IDApIGNhbGxiYWNrKCk7IH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBmbihhcnJheVtpXSwgY2hlY2spO1xufTtcblxuLypcbiAqIENvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUga2V5cyBpbiBvbmUgb2JqZWN0IGFuZCB0aGUga2V5c1xuICogaW4gYW5vdGhlciBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0ga2V5cyBkaWZmZXJlbmNlXG4gKi9cbmV4cG9ydHMua2V5c0RpZmZlcmVuY2UgPSBmdW5jdGlvbiAob2JqLCBvdGhlcikge1xuICAgIHZhciBkaWZmZXJlbmNlID0gW107XG4gICAgZm9yICh2YXIgaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKCEoaSBpbiBvdGhlcikpIHtcbiAgICAgICAgICAgIGRpZmZlcmVuY2UucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGlmZmVyZW5jZTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYSBkZXN0aW5hdGlvbiBvYmplY3QgYW5kIG9wdGlvbmFsbHkgbWFueSBzb3VyY2Ugb2JqZWN0cyxcbiAqIGNvcHkgYWxsIHByb3BlcnRpZXMgZnJvbSB0aGUgc291cmNlIG9iamVjdHMgaW50byB0aGUgZGVzdGluYXRpb24uXG4gKiBUaGUgbGFzdCBzb3VyY2Ugb2JqZWN0IGdpdmVuIG92ZXJyaWRlcyBwcm9wZXJ0aWVzIGZyb20gcHJldmlvdXNcbiAqIHNvdXJjZSBvYmplY3RzLlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3QgZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBzb3VyY2VzIGZyb20gd2hpY2ggcHJvcGVydGllcyBhcmUgcHVsbGVkXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBkZXN0XG4gKi9cbmV4cG9ydHMuZXh0ZW5kID0gZnVuY3Rpb24gKGRlc3QpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3JjID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrIGluIHNyYykge1xuICAgICAgICAgICAgZGVzdFtrXSA9IHNyY1trXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn07XG5cbi8qKlxuICogRXh0ZW5kIGEgZGVzdGluYXRpb24gb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb2YgdGhlIHNyYyBvYmplY3QsXG4gKiB1c2luZyBkZWZpbmVQcm9wZXJ0eSBpbnN0ZWFkIG9mIHNpbXBsZSBhc3NpZ25tZW50LlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBzcmNcbiAqIEByZXR1cm5zIHtPYmplY3R9IGRlc3RcbiAqL1xuZXhwb3J0cy5leHRlbmRBbGwgPSBmdW5jdGlvbiAoZGVzdCwgc3JjKSB7XG4gICAgZm9yICh2YXIgaSBpbiBzcmMpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIGksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc3JjLCBpKSk7XG4gICAgfVxuICAgIHJldHVybiBkZXN0O1xufTtcblxuLyoqXG4gKiBFeHRlbmQgYSBwYXJlbnQncyBwcm90b3R5cGUgd2l0aCBhbGwgcHJvcGVydGllcyBpbiBhIHByb3BlcnRpZXNcbiAqIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyZW50XG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAqIEByZXR1cm5zIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuaW5oZXJpdCA9IGZ1bmN0aW9uIChwYXJlbnQsIHByb3BzKSB7XG4gICAgdmFyIHBhcmVudFByb3RvID0gdHlwZW9mIHBhcmVudCA9PT0gJ2Z1bmN0aW9uJyA/IHBhcmVudC5wcm90b3R5cGUgOiBwYXJlbnQsXG4gICAgICAgIHByb3RvID0gT2JqZWN0LmNyZWF0ZShwYXJlbnRQcm90byk7XG4gICAgZXhwb3J0cy5leHRlbmRBbGwocHJvdG8sIHByb3BzKTtcbiAgICByZXR1cm4gcHJvdG87XG59O1xuXG4vKipcbiAqIEdpdmVuIGFuIG9iamVjdCBhbmQgYSBudW1iZXIgb2YgcHJvcGVydGllcyBhcyBzdHJpbmdzLCByZXR1cm4gdmVyc2lvblxuICogb2YgdGhhdCBvYmplY3Qgd2l0aCBvbmx5IHRob3NlIHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNyYyB0aGUgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IHByb3BlcnRpZXMgYW4gYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgY2hvc2VuXG4gKiB0byBhcHBlYXIgb24gdGhlIHJlc3VsdGluZyBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3Qgd2l0aCBsaW1pdGVkIHByb3BlcnRpZXMuXG4gKiBAZXhhbXBsZVxuICogdmFyIGZvbyA9IHsgbmFtZTogJ0NoYXJsaWUnLCBhZ2U6IDEwIH07XG4gKiB2YXIganVzdE5hbWUgPSBwaWNrKGZvbywgWyduYW1lJ10pO1xuICogLy8ganVzdE5hbWUgPSB7IG5hbWU6ICdDaGFybGllJyB9XG4gKi9cbmV4cG9ydHMucGljayA9IGZ1bmN0aW9uIChzcmMsIHByb3BlcnRpZXMpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgaWYgKGsgaW4gc3JjKSB7XG4gICAgICAgICAgICByZXN1bHRba10gPSBzcmNba107XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbnZhciBpZCA9IDE7XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pcXVlIG51bWVyaWMgaWQsIHN0YXJ0aW5nIGF0IDEgYW5kIGluY3JlbWVudGluZyB3aXRoXG4gKiBlYWNoIGNhbGwuXG4gKlxuICogQHJldHVybnMge051bWJlcn0gdW5pcXVlIG51bWVyaWMgaWQuXG4gKi9cbmV4cG9ydHMudW5pcXVlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGlkKys7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIHZlcnNpb24gb2YgYGZuYCB0aGF0IG9ubHkgZmlyZXMgb25jZSBldmVyeSBgdGltZWAgbWlsbHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gdGhlIGZ1bmN0aW9uIHRvIGJlIHRocm90dGxlZFxuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWUgbWlsbHNlY29uZHMgcmVxdWlyZWQgYmV0d2VlbiBmdW5jdGlvbiBjYWxsc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSB2YWx1ZSBvZiBgdGhpc2Agd2l0aCB3aGljaCB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IGRlYm91bmNlZCBmdW5jdGlvblxuICovXG5leHBvcnRzLnRocm90dGxlID0gZnVuY3Rpb24gKGZuLCB0aW1lLCBjb250ZXh0KSB7XG4gICAgdmFyIGxvY2ssIGFyZ3MsIHdyYXBwZXJGbiwgbGF0ZXI7XG5cbiAgICBsYXRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcbiAgICAgICAgbG9jayA9IGZhbHNlO1xuICAgICAgICBpZiAoYXJncykge1xuICAgICAgICAgICAgd3JhcHBlckZuLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgYXJncyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdyYXBwZXJGbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGxvY2spIHtcbiAgICAgICAgICAgIC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxuICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY2FsbCBhbmQgbG9jayB1bnRpbCBsYXRlclxuICAgICAgICAgICAgZm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xuICAgICAgICAgICAgbG9jayA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHdyYXBwZXJGbjtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgdmVyc2lvbiBvZiBgZm5gIHRoYXQgaXMgb25seSBjYWxsZWQgYHRpbWVgIG1pbGxpc2Vjb25kc1xuICogYWZ0ZXIgaXRzIGxhc3QgaW52b2NhdGlvblxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIHRoZSBmdW5jdGlvbiB0byBiZSBkZWJvdW5jZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lIG1pbGxzZWNvbmRzIGFmdGVyIHdoaWNoIHRoZSBmdW5jdGlvbiB3aWxsIGJlIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZGVib3VuY2VkIGZ1bmN0aW9uXG4gKi9cbmV4cG9ydHMuZGVib3VuY2UgPSBmdW5jdGlvbihmbiwgdGltZSkge1xuICAgIHZhciB0aW1lciwgYXJncztcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcblxuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgfSwgdGltZSk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYW4gYXJyYXkgb2YgbWVtYmVyIGZ1bmN0aW9uIG5hbWVzIGFzIHN0cmluZ3MsIHJlcGxhY2UgYWxsIG9mIHRoZW1cbiAqIHdpdGggYm91bmQgdmVyc2lvbnMgdGhhdCB3aWxsIGFsd2F5cyByZWZlciB0byBgY29udGV4dGAgYXMgYHRoaXNgLiBUaGlzXG4gKiBpcyB1c2VmdWwgZm9yIGNsYXNzZXMgd2hlcmUgb3RoZXJ3aXNlIGV2ZW50IGJpbmRpbmdzIHdvdWxkIHJlYXNzaWduXG4gKiBgdGhpc2AgdG8gdGhlIGV2ZW50ZWQgb2JqZWN0IG9yIHNvbWUgb3RoZXIgdmFsdWU6IHRoaXMgbGV0cyB5b3UgZW5zdXJlXG4gKiB0aGUgYHRoaXNgIHZhbHVlIGFsd2F5cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGZucyBsaXN0IG9mIG1lbWJlciBmdW5jdGlvbiBuYW1lc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSBjb250ZXh0IHZhbHVlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBjaGFuZ2VzIGZ1bmN0aW9ucyBpbi1wbGFjZVxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIE15Q2xhc3MoKSB7XG4gKiAgIGJpbmRBbGwoWydvbnRpbWVyJ10sIHRoaXMpO1xuICogICB0aGlzLm5hbWUgPSAnVG9tJztcbiAqIH1cbiAqIE15Q2xhc3MucHJvdG90eXBlLm9udGltZXIgPSBmdW5jdGlvbigpIHtcbiAqICAgYWxlcnQodGhpcy5uYW1lKTtcbiAqIH07XG4gKiB2YXIgbXlDbGFzcyA9IG5ldyBNeUNsYXNzKCk7XG4gKiBzZXRUaW1lb3V0KG15Q2xhc3Mub250aW1lciwgMTAwKTtcbiAqL1xuZXhwb3J0cy5iaW5kQWxsID0gZnVuY3Rpb24oZm5zLCBjb250ZXh0KSB7XG4gICAgZm5zLmZvckVhY2goZnVuY3Rpb24oZm4pIHtcbiAgICAgICAgY29udGV4dFtmbl0gPSBjb250ZXh0W2ZuXS5iaW5kKGNvbnRleHQpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlICdvcHRpb25zJyBwcm9wZXJ0eSBvbiBgb2JqYCB3aXRoIHByb3BlcnRpZXNcbiAqIGZyb20gdGhlIGBvcHRpb25zYCBhcmd1bWVudC4gUHJvcGVydGllcyBpbiB0aGUgYG9wdGlvbnNgXG4gKiBvYmplY3Qgd2lsbCBvdmVycmlkZSBleGlzdGluZyBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvYmplY3Qgb2Ygb3ZlcnJpZGUgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gZGVyaXZlZCBvcHRpb25zIG9iamVjdC5cbiAqL1xuZXhwb3J0cy5zZXRPcHRpb25zID0gZnVuY3Rpb24ob2JqLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSkge1xuICAgICAgICBvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gT2JqZWN0LmNyZWF0ZShvYmoub3B0aW9ucykgOiB7fTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XG4gICAgICAgIG9iai5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG9iai5vcHRpb25zO1xufTtcbiIsIi8vIChjKSBEZWFuIE1jTmFtZWUgPGRlYW5AZ21haWwuY29tPiwgMjAxMi5cbi8vXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZGVhbm0vY3NzLWNvbG9yLXBhcnNlci1qc1xuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4vLyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4vLyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtY29sb3IvXG52YXIga0NTU0NvbG9yVGFibGUgPSB7XG4gIFwidHJhbnNwYXJlbnRcIjogWzAsMCwwLDBdLCBcImFsaWNlYmx1ZVwiOiBbMjQwLDI0OCwyNTUsMV0sXG4gIFwiYW50aXF1ZXdoaXRlXCI6IFsyNTAsMjM1LDIxNSwxXSwgXCJhcXVhXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiYXF1YW1hcmluZVwiOiBbMTI3LDI1NSwyMTIsMV0sIFwiYXp1cmVcIjogWzI0MCwyNTUsMjU1LDFdLFxuICBcImJlaWdlXCI6IFsyNDUsMjQ1LDIyMCwxXSwgXCJiaXNxdWVcIjogWzI1NSwyMjgsMTk2LDFdLFxuICBcImJsYWNrXCI6IFswLDAsMCwxXSwgXCJibGFuY2hlZGFsbW9uZFwiOiBbMjU1LDIzNSwyMDUsMV0sXG4gIFwiYmx1ZVwiOiBbMCwwLDI1NSwxXSwgXCJibHVldmlvbGV0XCI6IFsxMzgsNDMsMjI2LDFdLFxuICBcImJyb3duXCI6IFsxNjUsNDIsNDIsMV0sIFwiYnVybHl3b29kXCI6IFsyMjIsMTg0LDEzNSwxXSxcbiAgXCJjYWRldGJsdWVcIjogWzk1LDE1OCwxNjAsMV0sIFwiY2hhcnRyZXVzZVwiOiBbMTI3LDI1NSwwLDFdLFxuICBcImNob2NvbGF0ZVwiOiBbMjEwLDEwNSwzMCwxXSwgXCJjb3JhbFwiOiBbMjU1LDEyNyw4MCwxXSxcbiAgXCJjb3JuZmxvd2VyYmx1ZVwiOiBbMTAwLDE0OSwyMzcsMV0sIFwiY29ybnNpbGtcIjogWzI1NSwyNDgsMjIwLDFdLFxuICBcImNyaW1zb25cIjogWzIyMCwyMCw2MCwxXSwgXCJjeWFuXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiZGFya2JsdWVcIjogWzAsMCwxMzksMV0sIFwiZGFya2N5YW5cIjogWzAsMTM5LDEzOSwxXSxcbiAgXCJkYXJrZ29sZGVucm9kXCI6IFsxODQsMTM0LDExLDFdLCBcImRhcmtncmF5XCI6IFsxNjksMTY5LDE2OSwxXSxcbiAgXCJkYXJrZ3JlZW5cIjogWzAsMTAwLDAsMV0sIFwiZGFya2dyZXlcIjogWzE2OSwxNjksMTY5LDFdLFxuICBcImRhcmtraGFraVwiOiBbMTg5LDE4MywxMDcsMV0sIFwiZGFya21hZ2VudGFcIjogWzEzOSwwLDEzOSwxXSxcbiAgXCJkYXJrb2xpdmVncmVlblwiOiBbODUsMTA3LDQ3LDFdLCBcImRhcmtvcmFuZ2VcIjogWzI1NSwxNDAsMCwxXSxcbiAgXCJkYXJrb3JjaGlkXCI6IFsxNTMsNTAsMjA0LDFdLCBcImRhcmtyZWRcIjogWzEzOSwwLDAsMV0sXG4gIFwiZGFya3NhbG1vblwiOiBbMjMzLDE1MCwxMjIsMV0sIFwiZGFya3NlYWdyZWVuXCI6IFsxNDMsMTg4LDE0MywxXSxcbiAgXCJkYXJrc2xhdGVibHVlXCI6IFs3Miw2MSwxMzksMV0sIFwiZGFya3NsYXRlZ3JheVwiOiBbNDcsNzksNzksMV0sXG4gIFwiZGFya3NsYXRlZ3JleVwiOiBbNDcsNzksNzksMV0sIFwiZGFya3R1cnF1b2lzZVwiOiBbMCwyMDYsMjA5LDFdLFxuICBcImRhcmt2aW9sZXRcIjogWzE0OCwwLDIxMSwxXSwgXCJkZWVwcGlua1wiOiBbMjU1LDIwLDE0NywxXSxcbiAgXCJkZWVwc2t5Ymx1ZVwiOiBbMCwxOTEsMjU1LDFdLCBcImRpbWdyYXlcIjogWzEwNSwxMDUsMTA1LDFdLFxuICBcImRpbWdyZXlcIjogWzEwNSwxMDUsMTA1LDFdLCBcImRvZGdlcmJsdWVcIjogWzMwLDE0NCwyNTUsMV0sXG4gIFwiZmlyZWJyaWNrXCI6IFsxNzgsMzQsMzQsMV0sIFwiZmxvcmFsd2hpdGVcIjogWzI1NSwyNTAsMjQwLDFdLFxuICBcImZvcmVzdGdyZWVuXCI6IFszNCwxMzksMzQsMV0sIFwiZnVjaHNpYVwiOiBbMjU1LDAsMjU1LDFdLFxuICBcImdhaW5zYm9yb1wiOiBbMjIwLDIyMCwyMjAsMV0sIFwiZ2hvc3R3aGl0ZVwiOiBbMjQ4LDI0OCwyNTUsMV0sXG4gIFwiZ29sZFwiOiBbMjU1LDIxNSwwLDFdLCBcImdvbGRlbnJvZFwiOiBbMjE4LDE2NSwzMiwxXSxcbiAgXCJncmF5XCI6IFsxMjgsMTI4LDEyOCwxXSwgXCJncmVlblwiOiBbMCwxMjgsMCwxXSxcbiAgXCJncmVlbnllbGxvd1wiOiBbMTczLDI1NSw0NywxXSwgXCJncmV5XCI6IFsxMjgsMTI4LDEyOCwxXSxcbiAgXCJob25leWRld1wiOiBbMjQwLDI1NSwyNDAsMV0sIFwiaG90cGlua1wiOiBbMjU1LDEwNSwxODAsMV0sXG4gIFwiaW5kaWFucmVkXCI6IFsyMDUsOTIsOTIsMV0sIFwiaW5kaWdvXCI6IFs3NSwwLDEzMCwxXSxcbiAgXCJpdm9yeVwiOiBbMjU1LDI1NSwyNDAsMV0sIFwia2hha2lcIjogWzI0MCwyMzAsMTQwLDFdLFxuICBcImxhdmVuZGVyXCI6IFsyMzAsMjMwLDI1MCwxXSwgXCJsYXZlbmRlcmJsdXNoXCI6IFsyNTUsMjQwLDI0NSwxXSxcbiAgXCJsYXduZ3JlZW5cIjogWzEyNCwyNTIsMCwxXSwgXCJsZW1vbmNoaWZmb25cIjogWzI1NSwyNTAsMjA1LDFdLFxuICBcImxpZ2h0Ymx1ZVwiOiBbMTczLDIxNiwyMzAsMV0sIFwibGlnaHRjb3JhbFwiOiBbMjQwLDEyOCwxMjgsMV0sXG4gIFwibGlnaHRjeWFuXCI6IFsyMjQsMjU1LDI1NSwxXSwgXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiOiBbMjUwLDI1MCwyMTAsMV0sXG4gIFwibGlnaHRncmF5XCI6IFsyMTEsMjExLDIxMSwxXSwgXCJsaWdodGdyZWVuXCI6IFsxNDQsMjM4LDE0NCwxXSxcbiAgXCJsaWdodGdyZXlcIjogWzIxMSwyMTEsMjExLDFdLCBcImxpZ2h0cGlua1wiOiBbMjU1LDE4MiwxOTMsMV0sXG4gIFwibGlnaHRzYWxtb25cIjogWzI1NSwxNjAsMTIyLDFdLCBcImxpZ2h0c2VhZ3JlZW5cIjogWzMyLDE3OCwxNzAsMV0sXG4gIFwibGlnaHRza3libHVlXCI6IFsxMzUsMjA2LDI1MCwxXSwgXCJsaWdodHNsYXRlZ3JheVwiOiBbMTE5LDEzNiwxNTMsMV0sXG4gIFwibGlnaHRzbGF0ZWdyZXlcIjogWzExOSwxMzYsMTUzLDFdLCBcImxpZ2h0c3RlZWxibHVlXCI6IFsxNzYsMTk2LDIyMiwxXSxcbiAgXCJsaWdodHllbGxvd1wiOiBbMjU1LDI1NSwyMjQsMV0sIFwibGltZVwiOiBbMCwyNTUsMCwxXSxcbiAgXCJsaW1lZ3JlZW5cIjogWzUwLDIwNSw1MCwxXSwgXCJsaW5lblwiOiBbMjUwLDI0MCwyMzAsMV0sXG4gIFwibWFnZW50YVwiOiBbMjU1LDAsMjU1LDFdLCBcIm1hcm9vblwiOiBbMTI4LDAsMCwxXSxcbiAgXCJtZWRpdW1hcXVhbWFyaW5lXCI6IFsxMDIsMjA1LDE3MCwxXSwgXCJtZWRpdW1ibHVlXCI6IFswLDAsMjA1LDFdLFxuICBcIm1lZGl1bW9yY2hpZFwiOiBbMTg2LDg1LDIxMSwxXSwgXCJtZWRpdW1wdXJwbGVcIjogWzE0NywxMTIsMjE5LDFdLFxuICBcIm1lZGl1bXNlYWdyZWVuXCI6IFs2MCwxNzksMTEzLDFdLCBcIm1lZGl1bXNsYXRlYmx1ZVwiOiBbMTIzLDEwNCwyMzgsMV0sXG4gIFwibWVkaXVtc3ByaW5nZ3JlZW5cIjogWzAsMjUwLDE1NCwxXSwgXCJtZWRpdW10dXJxdW9pc2VcIjogWzcyLDIwOSwyMDQsMV0sXG4gIFwibWVkaXVtdmlvbGV0cmVkXCI6IFsxOTksMjEsMTMzLDFdLCBcIm1pZG5pZ2h0Ymx1ZVwiOiBbMjUsMjUsMTEyLDFdLFxuICBcIm1pbnRjcmVhbVwiOiBbMjQ1LDI1NSwyNTAsMV0sIFwibWlzdHlyb3NlXCI6IFsyNTUsMjI4LDIyNSwxXSxcbiAgXCJtb2NjYXNpblwiOiBbMjU1LDIyOCwxODEsMV0sIFwibmF2YWpvd2hpdGVcIjogWzI1NSwyMjIsMTczLDFdLFxuICBcIm5hdnlcIjogWzAsMCwxMjgsMV0sIFwib2xkbGFjZVwiOiBbMjUzLDI0NSwyMzAsMV0sXG4gIFwib2xpdmVcIjogWzEyOCwxMjgsMCwxXSwgXCJvbGl2ZWRyYWJcIjogWzEwNywxNDIsMzUsMV0sXG4gIFwib3JhbmdlXCI6IFsyNTUsMTY1LDAsMV0sIFwib3JhbmdlcmVkXCI6IFsyNTUsNjksMCwxXSxcbiAgXCJvcmNoaWRcIjogWzIxOCwxMTIsMjE0LDFdLCBcInBhbGVnb2xkZW5yb2RcIjogWzIzOCwyMzIsMTcwLDFdLFxuICBcInBhbGVncmVlblwiOiBbMTUyLDI1MSwxNTIsMV0sIFwicGFsZXR1cnF1b2lzZVwiOiBbMTc1LDIzOCwyMzgsMV0sXG4gIFwicGFsZXZpb2xldHJlZFwiOiBbMjE5LDExMiwxNDcsMV0sIFwicGFwYXlhd2hpcFwiOiBbMjU1LDIzOSwyMTMsMV0sXG4gIFwicGVhY2hwdWZmXCI6IFsyNTUsMjE4LDE4NSwxXSwgXCJwZXJ1XCI6IFsyMDUsMTMzLDYzLDFdLFxuICBcInBpbmtcIjogWzI1NSwxOTIsMjAzLDFdLCBcInBsdW1cIjogWzIyMSwxNjAsMjIxLDFdLFxuICBcInBvd2RlcmJsdWVcIjogWzE3NiwyMjQsMjMwLDFdLCBcInB1cnBsZVwiOiBbMTI4LDAsMTI4LDFdLFxuICBcInJlZFwiOiBbMjU1LDAsMCwxXSwgXCJyb3N5YnJvd25cIjogWzE4OCwxNDMsMTQzLDFdLFxuICBcInJveWFsYmx1ZVwiOiBbNjUsMTA1LDIyNSwxXSwgXCJzYWRkbGVicm93blwiOiBbMTM5LDY5LDE5LDFdLFxuICBcInNhbG1vblwiOiBbMjUwLDEyOCwxMTQsMV0sIFwic2FuZHlicm93blwiOiBbMjQ0LDE2NCw5NiwxXSxcbiAgXCJzZWFncmVlblwiOiBbNDYsMTM5LDg3LDFdLCBcInNlYXNoZWxsXCI6IFsyNTUsMjQ1LDIzOCwxXSxcbiAgXCJzaWVubmFcIjogWzE2MCw4Miw0NSwxXSwgXCJzaWx2ZXJcIjogWzE5MiwxOTIsMTkyLDFdLFxuICBcInNreWJsdWVcIjogWzEzNSwyMDYsMjM1LDFdLCBcInNsYXRlYmx1ZVwiOiBbMTA2LDkwLDIwNSwxXSxcbiAgXCJzbGF0ZWdyYXlcIjogWzExMiwxMjgsMTQ0LDFdLCBcInNsYXRlZ3JleVwiOiBbMTEyLDEyOCwxNDQsMV0sXG4gIFwic25vd1wiOiBbMjU1LDI1MCwyNTAsMV0sIFwic3ByaW5nZ3JlZW5cIjogWzAsMjU1LDEyNywxXSxcbiAgXCJzdGVlbGJsdWVcIjogWzcwLDEzMCwxODAsMV0sIFwidGFuXCI6IFsyMTAsMTgwLDE0MCwxXSxcbiAgXCJ0ZWFsXCI6IFswLDEyOCwxMjgsMV0sIFwidGhpc3RsZVwiOiBbMjE2LDE5MSwyMTYsMV0sXG4gIFwidG9tYXRvXCI6IFsyNTUsOTksNzEsMV0sIFwidHVycXVvaXNlXCI6IFs2NCwyMjQsMjA4LDFdLFxuICBcInZpb2xldFwiOiBbMjM4LDEzMCwyMzgsMV0sIFwid2hlYXRcIjogWzI0NSwyMjIsMTc5LDFdLFxuICBcIndoaXRlXCI6IFsyNTUsMjU1LDI1NSwxXSwgXCJ3aGl0ZXNtb2tlXCI6IFsyNDUsMjQ1LDI0NSwxXSxcbiAgXCJ5ZWxsb3dcIjogWzI1NSwyNTUsMCwxXSwgXCJ5ZWxsb3dncmVlblwiOiBbMTU0LDIwNSw1MCwxXX1cblxuZnVuY3Rpb24gY2xhbXBfY3NzX2J5dGUoaSkgeyAgLy8gQ2xhbXAgdG8gaW50ZWdlciAwIC4uIDI1NS5cbiAgaSA9IE1hdGgucm91bmQoaSk7ICAvLyBTZWVtcyB0byBiZSB3aGF0IENocm9tZSBkb2VzICh2cyB0cnVuY2F0aW9uKS5cbiAgcmV0dXJuIGkgPCAwID8gMCA6IGkgPiAyNTUgPyAyNTUgOiBpO1xufVxuXG5mdW5jdGlvbiBjbGFtcF9jc3NfZmxvYXQoZikgeyAgLy8gQ2xhbXAgdG8gZmxvYXQgMC4wIC4uIDEuMC5cbiAgcmV0dXJuIGYgPCAwID8gMCA6IGYgPiAxID8gMSA6IGY7XG59XG5cbmZ1bmN0aW9uIHBhcnNlX2Nzc19pbnQoc3RyKSB7ICAvLyBpbnQgb3IgcGVyY2VudGFnZS5cbiAgaWYgKHN0cltzdHIubGVuZ3RoIC0gMV0gPT09ICclJylcbiAgICByZXR1cm4gY2xhbXBfY3NzX2J5dGUocGFyc2VGbG9hdChzdHIpIC8gMTAwICogMjU1KTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19ieXRlKHBhcnNlSW50KHN0cikpO1xufVxuXG5mdW5jdGlvbiBwYXJzZV9jc3NfZmxvYXQoc3RyKSB7ICAvLyBmbG9hdCBvciBwZXJjZW50YWdlLlxuICBpZiAoc3RyW3N0ci5sZW5ndGggLSAxXSA9PT0gJyUnKVxuICAgIHJldHVybiBjbGFtcF9jc3NfZmxvYXQocGFyc2VGbG9hdChzdHIpIC8gMTAwKTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19mbG9hdChwYXJzZUZsb2F0KHN0cikpO1xufVxuXG5mdW5jdGlvbiBjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgpIHtcbiAgaWYgKGggPCAwKSBoICs9IDE7XG4gIGVsc2UgaWYgKGggPiAxKSBoIC09IDE7XG5cbiAgaWYgKGggKiA2IDwgMSkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogaCAqIDY7XG4gIGlmIChoICogMiA8IDEpIHJldHVybiBtMjtcbiAgaWYgKGggKiAzIDwgMikgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDIvMyAtIGgpICogNjtcbiAgcmV0dXJuIG0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNTU0NvbG9yKGNzc19zdHIpIHtcbiAgLy8gUmVtb3ZlIGFsbCB3aGl0ZXNwYWNlLCBub3QgY29tcGxpYW50LCBidXQgc2hvdWxkIGp1c3QgYmUgbW9yZSBhY2NlcHRpbmcuXG4gIHZhciBzdHIgPSBjc3Nfc3RyLnJlcGxhY2UoLyAvZywgJycpLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gQ29sb3Iga2V5d29yZHMgKGFuZCB0cmFuc3BhcmVudCkgbG9va3VwLlxuICBpZiAoc3RyIGluIGtDU1NDb2xvclRhYmxlKSByZXR1cm4ga0NTU0NvbG9yVGFibGVbc3RyXS5zbGljZSgpOyAgLy8gZHVwLlxuXG4gIC8vICNhYmMgYW5kICNhYmMxMjMgc3ludGF4LlxuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gNCkge1xuICAgICAgdmFyIGl2ID0gcGFyc2VJbnQoc3RyLnN1YnN0cigxKSwgMTYpOyAgLy8gVE9ETyhkZWFubSk6IFN0cmljdGVyIHBhcnNpbmcuXG4gICAgICBpZiAoIShpdiA+PSAwICYmIGl2IDw9IDB4ZmZmKSkgcmV0dXJuIG51bGw7ICAvLyBDb3ZlcnMgTmFOLlxuICAgICAgcmV0dXJuIFsoKGl2ICYgMHhmMDApID4+IDQpIHwgKChpdiAmIDB4ZjAwKSA+PiA4KSxcbiAgICAgICAgICAgICAgKGl2ICYgMHhmMCkgfCAoKGl2ICYgMHhmMCkgPj4gNCksXG4gICAgICAgICAgICAgIChpdiAmIDB4ZikgfCAoKGl2ICYgMHhmKSA8PCA0KSxcbiAgICAgICAgICAgICAgMV07XG4gICAgfSBlbHNlIGlmIChzdHIubGVuZ3RoID09PSA3KSB7XG4gICAgICB2YXIgaXYgPSBwYXJzZUludChzdHIuc3Vic3RyKDEpLCAxNik7ICAvLyBUT0RPKGRlYW5tKTogU3RyaWN0ZXIgcGFyc2luZy5cbiAgICAgIGlmICghKGl2ID49IDAgJiYgaXYgPD0gMHhmZmZmZmYpKSByZXR1cm4gbnVsbDsgIC8vIENvdmVycyBOYU4uXG4gICAgICByZXR1cm4gWyhpdiAmIDB4ZmYwMDAwKSA+PiAxNixcbiAgICAgICAgICAgICAgKGl2ICYgMHhmZjAwKSA+PiA4LFxuICAgICAgICAgICAgICBpdiAmIDB4ZmYsXG4gICAgICAgICAgICAgIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIG9wID0gc3RyLmluZGV4T2YoJygnKSwgZXAgPSBzdHIuaW5kZXhPZignKScpO1xuICBpZiAob3AgIT09IC0xICYmIGVwICsgMSA9PT0gc3RyLmxlbmd0aCkge1xuICAgIHZhciBmbmFtZSA9IHN0ci5zdWJzdHIoMCwgb3ApO1xuICAgIHZhciBwYXJhbXMgPSBzdHIuc3Vic3RyKG9wKzEsIGVwLShvcCsxKSkuc3BsaXQoJywnKTtcbiAgICB2YXIgYWxwaGEgPSAxOyAgLy8gVG8gYWxsb3cgY2FzZSBmYWxsdGhyb3VnaC5cbiAgICBzd2l0Y2ggKGZuYW1lKSB7XG4gICAgICBjYXNlICdyZ2JhJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDQpIHJldHVybiBudWxsO1xuICAgICAgICBhbHBoYSA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXMucG9wKCkpO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2guXG4gICAgICBjYXNlICdyZ2InOlxuICAgICAgICBpZiAocGFyYW1zLmxlbmd0aCAhPT0gMykgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBbcGFyc2VfY3NzX2ludChwYXJhbXNbMF0pLFxuICAgICAgICAgICAgICAgIHBhcnNlX2Nzc19pbnQocGFyYW1zWzFdKSxcbiAgICAgICAgICAgICAgICBwYXJzZV9jc3NfaW50KHBhcmFtc1syXSksXG4gICAgICAgICAgICAgICAgYWxwaGFdO1xuICAgICAgY2FzZSAnaHNsYSc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSA0KSByZXR1cm4gbnVsbDtcbiAgICAgICAgYWxwaGEgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zLnBvcCgpKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoLlxuICAgICAgY2FzZSAnaHNsJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgaCA9ICgoKHBhcnNlRmxvYXQocGFyYW1zWzBdKSAlIDM2MCkgKyAzNjApICUgMzYwKSAvIDM2MDsgIC8vIDAgLi4gMVxuICAgICAgICAvLyBOT1RFKGRlYW5tKTogQWNjb3JkaW5nIHRvIHRoZSBDU1Mgc3BlYyBzL2wgc2hvdWxkIG9ubHkgYmVcbiAgICAgICAgLy8gcGVyY2VudGFnZXMsIGJ1dCB3ZSBkb24ndCBib3RoZXIgYW5kIGxldCBmbG9hdCBvciBwZXJjZW50YWdlLlxuICAgICAgICB2YXIgcyA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMV0pO1xuICAgICAgICB2YXIgbCA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMl0pO1xuICAgICAgICB2YXIgbTIgPSBsIDw9IDAuNSA/IGwgKiAocyArIDEpIDogbCArIHMgLSBsICogcztcbiAgICAgICAgdmFyIG0xID0gbCAqIDIgLSBtMjtcbiAgICAgICAgcmV0dXJuIFtjbGFtcF9jc3NfYnl0ZShjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgrMS8zKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoLTEvMykgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGFscGhhXTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG50cnkgeyBleHBvcnRzLnBhcnNlQ1NTQ29sb3IgPSBwYXJzZUNTU0NvbG9yIH0gY2F0Y2goZSkgeyB9XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZVR5cGVzID0gWydVbmtub3duJywgJ1BvaW50JywgJ0xpbmVTdHJpbmcnLCAnUG9seWdvbiddO1xuXG5mdW5jdGlvbiBpbmZpeChvcGVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiAndCcgKyBvcGVyYXRvciArIFZlY3RvclRpbGVGZWF0dXJlVHlwZXMuaW5kZXhPZih2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXScgKyBvcGVyYXRvciArIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdEluZml4KG9wZXJhdG9yKSB7XG4gICAgdmFyIG5vbnN0cmljdEluZml4ID0gaW5maXgob3BlcmF0b3IpO1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiBub25zdHJpY3RJbmZpeChfLCBrZXksIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAndHlwZW9mKHBbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSkgPT09IHR5cGVvZignICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpICsgJykgJiYgJyArXG4gICAgICAgICAgICAgICAgbm9uc3RyaWN0SW5maXgoXywga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgb3BlcmF0b3JzID0ge1xuICAgICc9PSc6IGluZml4KCc9PT0nKSxcbiAgICAnIT0nOiBpbmZpeCgnIT09JyksXG4gICAgJz4nOiBzdHJpY3RJbmZpeCgnPicpLFxuICAgICc8Jzogc3RyaWN0SW5maXgoJzwnKSxcbiAgICAnPD0nOiBzdHJpY3RJbmZpeCgnPD0nKSxcbiAgICAnPj0nOiBzdHJpY3RJbmZpeCgnPj0nKSxcbiAgICAnaW4nOiBmdW5jdGlvbihfLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMikubWFwKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gJygnICsgb3BlcmF0b3JzWyc9PSddKF8sIGtleSwgdmFsdWUpICsgJyknO1xuICAgICAgICB9KS5qb2luKCd8fCcpIHx8ICdmYWxzZSc7XG4gICAgfSxcbiAgICAnIWluJzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAnISgnICsgb3BlcmF0b3JzLmluLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKyAnKSc7XG4gICAgfSxcbiAgICAnYW55JzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLm1hcChmdW5jdGlvbihmaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBjb21waWxlKGZpbHRlcikgKyAnKSc7XG4gICAgICAgIH0pLmpvaW4oJ3x8JykgfHwgJ2ZhbHNlJztcbiAgICB9LFxuICAgICdhbGwnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkubWFwKGZ1bmN0aW9uKGZpbHRlcikge1xuICAgICAgICAgICAgcmV0dXJuICcoJyArIGNvbXBpbGUoZmlsdGVyKSArICcpJztcbiAgICAgICAgfSkuam9pbignJiYnKSB8fCAndHJ1ZSc7XG4gICAgfSxcbiAgICAnbm9uZSc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gJyEoJyArIG9wZXJhdG9ycy5hbnkuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICcpJztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb21waWxlKGZpbHRlcikge1xuICAgIHJldHVybiBvcGVyYXRvcnNbZmlsdGVyWzBdXS5hcHBseShmaWx0ZXIsIGZpbHRlcik7XG59XG5cbmZ1bmN0aW9uIHRydXRoKCkge1xuICAgIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgZmlsdGVyIGV4cHJlc3NlZCBhcyBuZXN0ZWQgYXJyYXlzLCByZXR1cm4gYSBuZXcgZnVuY3Rpb25cbiAqIHRoYXQgZXZhbHVhdGVzIHdoZXRoZXIgYSBnaXZlbiBmZWF0dXJlICh3aXRoIGEgLnByb3BlcnRpZXMgb3IgLnRhZ3MgcHJvcGVydHkpXG4gKiBwYXNzZXMgaXRzIHRlc3QuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gZmlsdGVyIG1hcGJveCBnbCBmaWx0ZXJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZmlsdGVyLWV2YWx1YXRpbmcgZnVuY3Rpb25cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgaWYgKCFmaWx0ZXIpIHJldHVybiB0cnV0aDtcbiAgICB2YXIgZmlsdGVyU3RyID0gJ3ZhciBwID0gZi5wcm9wZXJ0aWVzIHx8IGYudGFncyB8fCB7fSwgdCA9IGYudHlwZTsgcmV0dXJuICcgKyBjb21waWxlKGZpbHRlcikgKyAnOyc7XG4gICAgLy8ganNoaW50IGV2aWw6IHRydWVcbiAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCdmJywgZmlsdGVyU3RyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY2xpcDtcblxuLyogY2xpcCBmZWF0dXJlcyBiZXR3ZWVuIHR3byBheGlzLXBhcmFsbGVsIGxpbmVzOlxuICogICAgIHwgICAgICAgIHxcbiAqICBfX198X19fICAgICB8ICAgICAvXG4gKiAvICAgfCAgIFxcX19fX3xfX19fL1xuICogICAgIHwgICAgICAgIHxcbiAqL1xuXG5mdW5jdGlvbiBjbGlwKGZlYXR1cmVzLCBzY2FsZSwgazEsIGsyLCBheGlzLCBpbnRlcnNlY3QpIHtcblxuICAgIGsxIC89IHNjYWxlO1xuICAgIGsyIC89IHNjYWxlO1xuXG4gICAgdmFyIGNsaXBwZWQgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldLFxuICAgICAgICAgICAgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICAgICAgdHlwZSA9IGZlYXR1cmUudHlwZSxcbiAgICAgICAgICAgIG1pbiwgbWF4O1xuXG4gICAgICAgIGlmIChmZWF0dXJlLm1pbikge1xuICAgICAgICAgICAgbWluID0gZmVhdHVyZS5taW5bYXhpc107XG4gICAgICAgICAgICBtYXggPSBmZWF0dXJlLm1heFtheGlzXTtcblxuICAgICAgICAgICAgaWYgKG1pbiA+PSBrMSAmJiBtYXggPD0gazIpIHsgLy8gdHJpdmlhbCBhY2NlcHRcbiAgICAgICAgICAgICAgICBjbGlwcGVkLnB1c2goZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IGsyIHx8IG1heCA8IGsxKSBjb250aW51ZTsgLy8gdHJpdmlhbCByZWplY3RcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzbGljZXMgPSB0eXBlID09PSAxID9cbiAgICAgICAgICAgICAgICBjbGlwUG9pbnRzKGdlb21ldHJ5LCBrMSwgazIsIGF4aXMpIDpcbiAgICAgICAgICAgICAgICBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCB0eXBlID09PSAzKTtcblxuICAgICAgICBpZiAoc2xpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gaWYgYSBmZWF0dXJlIGdvdCBjbGlwcGVkLCBpdCB3aWxsIGxpa2VseSBnZXQgY2xpcHBlZCBvbiB0aGUgbmV4dCB6b29tIGxldmVsIGFzIHdlbGwsXG4gICAgICAgICAgICAvLyBzbyB0aGVyZSdzIG5vIG5lZWQgdG8gcmVjYWxjdWxhdGUgYmJveGVzXG4gICAgICAgICAgICBjbGlwcGVkLnB1c2goe1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5OiBzbGljZXMsXG4gICAgICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgICAgICB0YWdzOiBmZWF0dXJlc1tpXS50YWdzIHx8IG51bGxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWQubGVuZ3RoID8gY2xpcHBlZCA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGNsaXBQb2ludHMoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcykge1xuICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBnZW9tZXRyeS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYSA9IGdlb21ldHJ5W2ldLFxuICAgICAgICAgICAgYWsgPSBhW2F4aXNdO1xuXG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcbiAgICB9XG4gICAgcmV0dXJuIHNsaWNlO1xufVxuXG5mdW5jdGlvbiBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCBjbG9zZWQpIHtcblxuICAgIHZhciBzbGljZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgYWsgPSAwLFxuICAgICAgICAgICAgYmsgPSAwLFxuICAgICAgICAgICAgYiA9IG51bGwsXG4gICAgICAgICAgICBwb2ludHMgPSBnZW9tZXRyeVtpXSxcbiAgICAgICAgICAgIGFyZWEgPSBwb2ludHMuYXJlYSxcbiAgICAgICAgICAgIGRpc3QgPSBwb2ludHMuZGlzdCxcbiAgICAgICAgICAgIGxlbiA9IHBvaW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhLCBqO1xuXG4gICAgICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW4gLSAxOyBqKyspIHtcbiAgICAgICAgICAgIGEgPSBiIHx8IHBvaW50c1tqXTtcbiAgICAgICAgICAgIGIgPSBwb2ludHNbaiArIDFdO1xuICAgICAgICAgICAgYWsgPSBiayB8fCBhW2F4aXNdO1xuICAgICAgICAgICAgYmsgPSBiW2F4aXNdO1xuXG4gICAgICAgICAgICBpZiAoYWsgPCBrMSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKChiayA+IGsyKSkgeyAvLyAtLS18LS0tLS18LS0+XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSwgaW50ZXJzZWN0KGEsIGIsIGsyKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+PSBrMSkgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazEpKTsgLy8gLS0tfC0tPiAgfFxuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFrID4gazIpIHtcblxuICAgICAgICAgICAgICAgIGlmICgoYmsgPCBrMSkpIHsgLy8gPC0tfC0tLS0tfC0tLVxuICAgICAgICAgICAgICAgICAgICBzbGljZS5wdXNoKGludGVyc2VjdChhLCBiLCBrMiksIGludGVyc2VjdChhLCBiLCBrMSkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb3NlZCkgc2xpY2UgPSBuZXdTbGljZShzbGljZXMsIHNsaWNlLCBhcmVhLCBkaXN0KTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmsgPD0gazIpIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsyKSk7IC8vIHwgIDwtLXwtLS1cblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goYSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYmsgPCBrMSkgeyAvLyA8LS18LS0tICB8XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+IGsyKSB7IC8vIHwgIC0tLXwtLT5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjbG9zZWQpIHNsaWNlID0gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHwgLS0+IHxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkZCB0aGUgbGFzdCBwb2ludFxuICAgICAgICBhID0gcG9pbnRzW2xlbiAtIDFdO1xuICAgICAgICBhayA9IGFbYXhpc107XG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcblxuICAgICAgICAvLyBjbG9zZSB0aGUgcG9seWdvbiBpZiBpdHMgZW5kcG9pbnRzIGFyZSBub3QgdGhlIHNhbWUgYWZ0ZXIgY2xpcHBpbmdcbiAgICAgICAgaWYgKGNsb3NlZCAmJiBzbGljZVswXSAhPT0gc2xpY2Vbc2xpY2UubGVuZ3RoIC0gMV0pIHNsaWNlLnB1c2goc2xpY2VbMF0pO1xuXG4gICAgICAgIC8vIGFkZCB0aGUgZmluYWwgc2xpY2VcbiAgICAgICAgbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWNlcztcbn1cblxuZnVuY3Rpb24gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCkge1xuICAgIGlmIChzbGljZS5sZW5ndGgpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3QgcmVjYWxjdWxhdGUgdGhlIGFyZWEvbGVuZ3RoIG9mIHRoZSB1bmNsaXBwZWQgZ2VvbWV0cnkgYmVjYXVzZSB0aGUgY2FzZSB3aGVyZSBpdCBnb2VzXG4gICAgICAgIC8vIGJlbG93IHRoZSB2aXNpYmlsaXR5IHRocmVzaG9sZCBhcyBhIHJlc3VsdCBvZiBjbGlwcGluZyBpcyByYXJlLCBzbyB3ZSBhdm9pZCBkb2luZyB1bm5lY2Vzc2FyeSB3b3JrXG4gICAgICAgIHNsaWNlLmFyZWEgPSBhcmVhO1xuICAgICAgICBzbGljZS5kaXN0ID0gZGlzdDtcblxuICAgICAgICBzbGljZXMucHVzaChzbGljZSk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXJ0O1xuXG52YXIgc2ltcGxpZnkgPSByZXF1aXJlKCcuL3NpbXBsaWZ5Jyk7XG5cbi8vIGNvbnZlcnRzIEdlb0pTT04gZmVhdHVyZSBpbnRvIGFuIGludGVybWVkaWF0ZSBwcm9qZWN0ZWQgSlNPTiB2ZWN0b3IgZm9ybWF0IHdpdGggc2ltcGxpZmljYXRpb24gZGF0YVxuXG5mdW5jdGlvbiBjb252ZXJ0KGRhdGEsIHRvbGVyYW5jZSkge1xuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEuZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnZlcnRGZWF0dXJlKGZlYXR1cmVzLCBkYXRhLmZlYXR1cmVzW2ldLCB0b2xlcmFuY2UpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdGZWF0dXJlJykge1xuICAgICAgICBjb252ZXJ0RmVhdHVyZShmZWF0dXJlcywgZGF0YSwgdG9sZXJhbmNlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNpbmdsZSBnZW9tZXRyeSBvciBhIGdlb21ldHJ5IGNvbGxlY3Rpb25cbiAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtnZW9tZXRyeTogZGF0YX0sIHRvbGVyYW5jZSk7XG4gICAgfVxuICAgIHJldHVybiBmZWF0dXJlcztcbn1cblxuZnVuY3Rpb24gY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIGZlYXR1cmUsIHRvbGVyYW5jZSkge1xuICAgIHZhciBnZW9tID0gZmVhdHVyZS5nZW9tZXRyeSxcbiAgICAgICAgdHlwZSA9IGdlb20udHlwZSxcbiAgICAgICAgY29vcmRzID0gZ2VvbS5jb29yZGluYXRlcyxcbiAgICAgICAgdGFncyA9IGZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgaSwgaiwgcmluZ3M7XG5cbiAgICBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBbcHJvamVjdFBvaW50KGNvb3JkcyldKSk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdNdWx0aVBvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBwcm9qZWN0KGNvb3JkcykpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0xpbmVTdHJpbmcnKSB7XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIDIsIFtwcm9qZWN0KGNvb3JkcywgdG9sZXJhbmNlKV0pKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ011bHRpTGluZVN0cmluZycgfHwgdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIHJpbmdzID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmdzLnB1c2gocHJvamVjdChjb29yZHNbaV0sIHRvbGVyYW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIHR5cGUgPT09ICdQb2x5Z29uJyA/IDMgOiAyLCByaW5ncykpO1xuXG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICByaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29vcmRzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChwcm9qZWN0KGNvb3Jkc1tpXVtqXSwgdG9sZXJhbmNlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmVhdHVyZXMucHVzaChjcmVhdGUodGFncywgMywgcmluZ3MpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20uZ2VvbWV0cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeTogZ2VvbS5nZW9tZXRyaWVzW2ldLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHRhZ3NcbiAgICAgICAgICAgIH0sIHRvbGVyYW5jZSk7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVW5zdXBwb3J0ZWQgR2VvSlNPTiB0eXBlOiAnICsgZ2VvbS50eXBlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZSh0YWdzLCB0eXBlLCBnZW9tZXRyeSkge1xuICAgIHZhciBmZWF0dXJlID0ge1xuICAgICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIHRhZ3M6IHRhZ3MgfHwgbnVsbCxcbiAgICAgICAgbWluOiBbMSwgMV0sIC8vIGluaXRpYWwgYmJveCB2YWx1ZXM7XG4gICAgICAgIG1heDogWzAsIDBdICAvLyBub3RlIHRoYXQgYWxsIGNvb3JkcyBhcmUgaW4gWzAuLjFdIHJhbmdlXG4gICAgfTtcbiAgICBjYWxjQkJveChmZWF0dXJlKTtcbiAgICByZXR1cm4gZmVhdHVyZTtcbn1cblxuZnVuY3Rpb24gcHJvamVjdChsb25sYXRzLCB0b2xlcmFuY2UpIHtcbiAgICB2YXIgcHJvamVjdGVkID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb25sYXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByb2plY3RlZC5wdXNoKHByb2plY3RQb2ludChsb25sYXRzW2ldKSk7XG4gICAgfVxuICAgIGlmICh0b2xlcmFuY2UpIHtcbiAgICAgICAgc2ltcGxpZnkocHJvamVjdGVkLCB0b2xlcmFuY2UpO1xuICAgICAgICBjYWxjU2l6ZShwcm9qZWN0ZWQpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvamVjdGVkO1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0UG9pbnQocCkge1xuICAgIHZhciBzaW4gPSBNYXRoLnNpbihwWzFdICogTWF0aC5QSSAvIDE4MCksXG4gICAgICAgIHggPSAocFswXSAvIDM2MCArIDAuNSksXG4gICAgICAgIHkgPSAoMC41IC0gMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyBNYXRoLlBJKTtcbiAgICByZXR1cm4gW3gsIHksIDBdO1xufVxuXG4vLyBjYWxjdWxhdGUgYXJlYSBhbmQgbGVuZ3RoIG9mIHRoZSBwb2x5XG5mdW5jdGlvbiBjYWxjU2l6ZShwb2ludHMpIHtcbiAgICB2YXIgYXJlYSA9IDAsXG4gICAgICAgIGRpc3QgPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGEsIGI7IGkgPCBwb2ludHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGEgPSBiIHx8IHBvaW50c1tpXTtcbiAgICAgICAgYiA9IHBvaW50c1tpICsgMV07XG5cbiAgICAgICAgYXJlYSArPSBhWzBdICogYlsxXSAtIGJbMF0gKiBhWzFdO1xuXG4gICAgICAgIC8vIHVzZSBNYW5oYXR0YW4gZGlzdGFuY2UgaW5zdGVhZCBvZiBFdWNsaWRpYW4gb25lIHRvIGF2b2lkIGV4cGVuc2l2ZSBzcXVhcmUgcm9vdCBjb21wdXRhdGlvblxuICAgICAgICBkaXN0ICs9IE1hdGguYWJzKGJbMF0gLSBhWzBdKSArIE1hdGguYWJzKGJbMV0gLSBhWzFdKTtcbiAgICB9XG4gICAgcG9pbnRzLmFyZWEgPSBNYXRoLmFicyhhcmVhIC8gMik7XG4gICAgcG9pbnRzLmRpc3QgPSBkaXN0O1xufVxuXG4vLyBjYWxjdWxhdGUgdGhlIGZlYXR1cmUgYm91bmRpbmcgYm94IGZvciBmYXN0ZXIgY2xpcHBpbmcgbGF0ZXJcbmZ1bmN0aW9uIGNhbGNCQm94KGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICBtaW4gPSBmZWF0dXJlLm1pbixcbiAgICAgICAgbWF4ID0gZmVhdHVyZS5tYXg7XG5cbiAgICBpZiAoZmVhdHVyZS50eXBlID09PSAxKSBjYWxjUmluZ0JCb3gobWluLCBtYXgsIGdlb21ldHJ5KTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIGNhbGNSaW5nQkJveChtaW4sIG1heCwgZ2VvbWV0cnlbaV0pO1xuXG4gICAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGNhbGNSaW5nQkJveChtaW4sIG1heCwgcG9pbnRzKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcCA9IHBvaW50c1tpXTtcbiAgICAgICAgbWluWzBdID0gTWF0aC5taW4ocFswXSwgbWluWzBdKTtcbiAgICAgICAgbWF4WzBdID0gTWF0aC5tYXgocFswXSwgbWF4WzBdKTtcbiAgICAgICAgbWluWzFdID0gTWF0aC5taW4ocFsxXSwgbWluWzFdKTtcbiAgICAgICAgbWF4WzFdID0gTWF0aC5tYXgocFsxXSwgbWF4WzFdKTtcbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZ2VvanNvbnZ0O1xuXG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4vY29udmVydCcpLCAvLyBHZW9KU09OIGNvbnZlcnNpb24gYW5kIHByZXByb2Nlc3NpbmdcbiAgICBjbGlwID0gcmVxdWlyZSgnLi9jbGlwJyksICAgICAgIC8vIHN0cmlwZSBjbGlwcGluZyBhbGdvcml0aG1cbiAgICBjcmVhdGVUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7IC8vIGZpbmFsIHNpbXBsaWZpZWQgdGlsZSBnZW5lcmF0aW9uXG5cblxuZnVuY3Rpb24gZ2VvanNvbnZ0KGRhdGEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IEdlb0pTT05WVChkYXRhLCBvcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gR2VvSlNPTlZUKGRhdGEsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zID0gZXh0ZW5kKE9iamVjdC5jcmVhdGUodGhpcy5vcHRpb25zKSwgb3B0aW9ucyk7XG5cbiAgICB2YXIgZGVidWcgPSBvcHRpb25zLmRlYnVnO1xuXG4gICAgaWYgKGRlYnVnKSBjb25zb2xlLnRpbWUoJ3ByZXByb2Nlc3MgZGF0YScpO1xuXG4gICAgdmFyIHoyID0gMSA8PCBvcHRpb25zLmJhc2Vab29tLCAvLyAyXnpcbiAgICAgICAgZmVhdHVyZXMgPSBjb252ZXJ0KGRhdGEsIG9wdGlvbnMudG9sZXJhbmNlIC8gKHoyICogb3B0aW9ucy5leHRlbnQpKTtcblxuICAgIHRoaXMudGlsZXMgPSB7fTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoJ3ByZXByb2Nlc3MgZGF0YScpO1xuICAgICAgICBjb25zb2xlLnRpbWUoJ2dlbmVyYXRlIHRpbGVzIHVwIHRvIHonICsgb3B0aW9ucy5tYXhab29tKTtcbiAgICAgICAgdGhpcy5zdGF0cyA9IHt9O1xuICAgICAgICB0aGlzLnRvdGFsID0gMDtcbiAgICB9XG5cbiAgICAvLyBzdGFydCBzbGljaW5nIGZyb20gdGhlIHRvcCB0aWxlIGRvd25cbiAgICB0aGlzLnNwbGl0VGlsZShmZWF0dXJlcywgMCwgMCwgMCk7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2ZlYXR1cmVzOiAlZCwgcG9pbnRzOiAlZCcsIHRoaXMudGlsZXNbMF0ubnVtRmVhdHVyZXMsIHRoaXMudGlsZXNbMF0ubnVtUG9pbnRzKTtcbiAgICAgICAgY29uc29sZS50aW1lRW5kKCdnZW5lcmF0ZSB0aWxlcyB1cCB0byB6JyArIG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCd0aWxlcyBnZW5lcmF0ZWQ6JywgdGhpcy50b3RhbCwgSlNPTi5zdHJpbmdpZnkodGhpcy5zdGF0cykpO1xuICAgIH1cbn1cblxuR2VvSlNPTlZULnByb3RvdHlwZS5vcHRpb25zID0ge1xuICAgIGJhc2Vab29tOiAxNCwgICAvLyBtYXggem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgb25cbiAgICBtYXhab29tOiA0LCAgICAgLy8gem9vbSB0byBzbGljZSBkb3duIHRvIG9uIGZpcnN0IHBhc3NcbiAgICBtYXhQb2ludHM6IDEwMCwgLy8gc3RvcCBzbGljaW5nIGEgdGlsZSBiZWxvdyB0aGlzIG51bWJlciBvZiBwb2ludHNcbiAgICB0b2xlcmFuY2U6IDMsICAgLy8gc2ltcGxpZmljYXRpb24gdG9sZXJhbmNlIChoaWdoZXIgbWVhbnMgc2ltcGxlcilcbiAgICBleHRlbnQ6IDQwOTYsICAgLy8gdGlsZSBleHRlbnRcbiAgICBidWZmZXI6IDY0LCAgICAgLy8gdGlsZSBidWZmZXIgb24gZWFjaCBzaWRlXG4gICAgZGVidWc6IDAgICAgICAgIC8vIGxvZ2dpbmcgbGV2ZWwgKDAsIDEgb3IgMilcbn07XG5cbkdlb0pTT05WVC5wcm90b3R5cGUuc3BsaXRUaWxlID0gZnVuY3Rpb24gKGZlYXR1cmVzLCB6LCB4LCB5LCBjeiwgY3gsIGN5KSB7XG5cbiAgICB2YXIgc3RhY2sgPSBbZmVhdHVyZXMsIHosIHgsIHldLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICBkZWJ1ZyA9IG9wdGlvbnMuZGVidWcsXG4gICAgICAgIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50LFxuICAgICAgICBidWZmZXIgPSBvcHRpb25zLmJ1ZmZlcjtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHByb2Nlc3NpbmcgcXVldWVcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoKSB7XG4gICAgICAgIGZlYXR1cmVzID0gc3RhY2suc2hpZnQoKTtcbiAgICAgICAgeiA9IHN0YWNrLnNoaWZ0KCk7XG4gICAgICAgIHggPSBzdGFjay5zaGlmdCgpO1xuICAgICAgICB5ID0gc3RhY2suc2hpZnQoKTtcblxuICAgICAgICB2YXIgejIgPSAxIDw8IHosXG4gICAgICAgICAgICBpZCA9IHRvSUQoeiwgeCwgeSksXG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF0sXG4gICAgICAgICAgICB0aWxlVG9sZXJhbmNlID0geiA9PT0gb3B0aW9ucy5iYXNlWm9vbSA/IDAgOiBvcHRpb25zLnRvbGVyYW5jZSAvICh6MiAqIGV4dGVudCk7XG5cbiAgICAgICAgaWYgKCF0aWxlKSB7XG4gICAgICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NyZWF0aW9uJyk7XG5cbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLnRpbGVzW2lkXSA9IGNyZWF0ZVRpbGUoZmVhdHVyZXMsIHoyLCB4LCB5LCB0aWxlVG9sZXJhbmNlLCBleHRlbnQsIHogPT09IG9wdGlvbnMuYmFzZVpvb20pO1xuXG4gICAgICAgICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVidWcgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCd0aWxlIHolZC0lZC0lZCAoZmVhdHVyZXM6ICVkLCBwb2ludHM6ICVkLCBzaW1wbGlmaWVkOiAlZCknLFxuICAgICAgICAgICAgICAgICAgICAgICAgeiwgeCwgeSwgdGlsZS5udW1GZWF0dXJlcywgdGlsZS5udW1Qb2ludHMsIHRpbGUubnVtU2ltcGxpZmllZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZCgnY3JlYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICd6JyArIHogKyAnOic7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0c1trZXldID0gKHRoaXMuc3RhdHNba2V5XSB8fCAwKSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy50b3RhbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjeiAmJiAoeiA9PT0gb3B0aW9ucy5tYXhab29tIHx8IHRpbGUubnVtUG9pbnRzIDw9IG9wdGlvbnMubWF4UG9pbnRzIHx8XG4gICAgICAgICAgICAgICAgaXNDbGlwcGVkU3F1YXJlKHRpbGUuZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSkgfHwgeiA9PT0gb3B0aW9ucy5iYXNlWm9vbSB8fCB6ID09PSBjeikge1xuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSBmZWF0dXJlcztcbiAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBzdG9wIHRpbGluZ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN6KSB0aWxlLnNvdXJjZSA9IGZlYXR1cmVzO1xuICAgICAgICBlbHNlIHRpbGUuc291cmNlID0gbnVsbDtcblxuICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NsaXBwaW5nJyk7XG5cbiAgICAgICAgLy8gdmFsdWVzIHdlJ2xsIHVzZSBmb3IgY2xpcHBpbmdcbiAgICAgICAgdmFyIGsxID0gMC41ICogYnVmZmVyIC8gZXh0ZW50LFxuICAgICAgICAgICAgazIgPSAwLjUgLSBrMSxcbiAgICAgICAgICAgIGszID0gMC41ICsgazEsXG4gICAgICAgICAgICBrNCA9IDEgKyBrMSxcblxuICAgICAgICAgICAgdGwsIGJsLCB0ciwgYnIsIGxlZnQsIHJpZ2h0LFxuICAgICAgICAgICAgbSwgZ29MZWZ0LCBnb1RvcDtcblxuICAgICAgICBpZiAoY3opIHsgLy8gaWYgd2UgaGF2ZSBhIHNwZWNpZmljIHRpbGUgdG8gZHJpbGwgZG93biB0bywgY2FsY3VsYXRlIHdoZXJlIHRvIGdvXG4gICAgICAgICAgICBtID0gMSA8PCAoY3ogLSB6KTtcbiAgICAgICAgICAgIGdvTGVmdCA9IGN4IC8gbSAtIHggPCAwLjU7XG4gICAgICAgICAgICBnb1RvcCA9IGN5IC8gbSAtIHkgPCAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICB0bCA9IGJsID0gdHIgPSBiciA9IGxlZnQgPSByaWdodCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCFjeiB8fCAgZ29MZWZ0KSBsZWZ0ICA9IGNsaXAoZmVhdHVyZXMsIHoyLCB4IC0gazEsIHggKyBrMywgMCwgaW50ZXJzZWN0WCk7XG4gICAgICAgIGlmICghY3ogfHwgIWdvTGVmdCkgcmlnaHQgPSBjbGlwKGZlYXR1cmVzLCB6MiwgeCArIGsyLCB4ICsgazQsIDAsIGludGVyc2VjdFgpO1xuXG4gICAgICAgIGlmIChsZWZ0KSB7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICBnb1RvcCkgdGwgPSBjbGlwKGxlZnQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYmwgPSBjbGlwKGxlZnQsIHoyLCB5ICsgazIsIHkgKyBrNCwgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgIGlmICghY3ogfHwgIGdvVG9wKSB0ciA9IGNsaXAocmlnaHQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYnIgPSBjbGlwKHJpZ2h0LCB6MiwgeSArIGsyLCB5ICsgazQsIDEsIGludGVyc2VjdFkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS50aW1lRW5kKCdjbGlwcGluZycpO1xuXG4gICAgICAgIGlmICh0bCkgc3RhY2sucHVzaCh0bCwgeiArIDEsIHggKiAyLCAgICAgeSAqIDIpO1xuICAgICAgICBpZiAoYmwpIHN0YWNrLnB1c2goYmwsIHogKyAxLCB4ICogMiwgICAgIHkgKiAyICsgMSk7XG4gICAgICAgIGlmICh0cikgc3RhY2sucHVzaCh0ciwgeiArIDEsIHggKiAyICsgMSwgeSAqIDIpO1xuICAgICAgICBpZiAoYnIpIHN0YWNrLnB1c2goYnIsIHogKyAxLCB4ICogMiArIDEsIHkgKiAyICsgMSk7XG4gICAgfVxufTtcblxuR2VvSlNPTlZULnByb3RvdHlwZS5nZXRUaWxlID0gZnVuY3Rpb24gKHosIHgsIHkpIHtcbiAgICB2YXIgaWQgPSB0b0lEKHosIHgsIHkpO1xuICAgIGlmICh0aGlzLnRpbGVzW2lkXSkgcmV0dXJuIHRoaXMudGlsZXNbaWRdO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgIGRlYnVnID0gb3B0aW9ucy5kZWJ1ZztcblxuICAgIGlmIChkZWJ1ZyA+IDEpIGNvbnNvbGUubG9nKCdkcmlsbGluZyBkb3duIHRvIHolZC0lZC0lZCcsIHosIHgsIHkpO1xuXG4gICAgdmFyIHowID0geixcbiAgICAgICAgeDAgPSB4LFxuICAgICAgICB5MCA9IHksXG4gICAgICAgIHBhcmVudDtcblxuICAgIHdoaWxlICghcGFyZW50ICYmIHowID4gMCkge1xuICAgICAgICB6MC0tO1xuICAgICAgICB4MCA9IE1hdGguZmxvb3IoeDAgLyAyKTtcbiAgICAgICAgeTAgPSBNYXRoLmZsb29yKHkwIC8gMik7XG4gICAgICAgIHBhcmVudCA9IHRoaXMudGlsZXNbdG9JRCh6MCwgeDAsIHkwKV07XG4gICAgfVxuXG4gICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS5sb2coJ2ZvdW5kIHBhcmVudCB0aWxlIHolZC0lZC0lZCcsIHowLCB4MCwgeTApO1xuXG4gICAgLy8gaWYgd2UgZm91bmQgYSBwYXJlbnQgdGlsZSBjb250YWluaW5nIHRoZSBvcmlnaW5hbCBnZW9tZXRyeSwgd2UgY2FuIGRyaWxsIGRvd24gZnJvbSBpdFxuICAgIGlmIChwYXJlbnQuc291cmNlKSB7XG4gICAgICAgIGlmIChpc0NsaXBwZWRTcXVhcmUocGFyZW50LmZlYXR1cmVzLCBvcHRpb25zLmV4dGVudCwgb3B0aW9ucy5idWZmZXIpKSByZXR1cm4gcGFyZW50O1xuXG4gICAgICAgIGlmIChkZWJ1ZykgY29uc29sZS50aW1lKCdkcmlsbGluZyBkb3duJyk7XG4gICAgICAgIHRoaXMuc3BsaXRUaWxlKHBhcmVudC5zb3VyY2UsIHowLCB4MCwgeTAsIHosIHgsIHkpO1xuICAgICAgICBpZiAoZGVidWcpIGNvbnNvbGUudGltZUVuZCgnZHJpbGxpbmcgZG93bicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRpbGVzW2lkXTtcbn07XG5cbi8vIGNoZWNrcyB3aGV0aGVyIGEgdGlsZSBpcyBhIHdob2xlLWFyZWEgZmlsbCBhZnRlciBjbGlwcGluZzsgaWYgaXQgaXMsIHRoZXJlJ3Mgbm8gc2Vuc2Ugc2xpY2luZyBpdCBmdXJ0aGVyXG5mdW5jdGlvbiBpc0NsaXBwZWRTcXVhcmUoZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSB7XG4gICAgaWYgKGZlYXR1cmVzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1swXTtcbiAgICBpZiAoZmVhdHVyZS50eXBlICE9PSAzIHx8IGZlYXR1cmUuZ2VvbWV0cnkubGVuZ3RoID4gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlLmdlb21ldHJ5WzBdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwID0gZmVhdHVyZS5nZW9tZXRyeVswXVtpXTtcbiAgICAgICAgaWYgKChwWzBdICE9PSAtYnVmZmVyICYmIHBbMF0gIT09IGV4dGVudCArIGJ1ZmZlcikgfHxcbiAgICAgICAgICAgIChwWzFdICE9PSAtYnVmZmVyICYmIHBbMV0gIT09IGV4dGVudCArIGJ1ZmZlcikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHRvSUQoeiwgeCwgeSkge1xuICAgIHJldHVybiAoKCgxIDw8IHopICogeSArIHgpICogMzIpICsgejtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0WChhLCBiLCB4KSB7XG4gICAgcmV0dXJuIFt4LCAoeCAtIGFbMF0pICogKGJbMV0gLSBhWzFdKSAvIChiWzBdIC0gYVswXSkgKyBhWzFdLCAxXTtcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFkoYSwgYiwgeSkge1xuICAgIHJldHVybiBbKHkgLSBhWzFdKSAqIChiWzBdIC0gYVswXSkgLyAoYlsxXSAtIGFbMV0pICsgYVswXSwgeSwgMV07XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMpIHtcbiAgICBmb3IgKHZhciBpIGluIHNyYykgZGVzdFtpXSA9IHNyY1tpXTtcbiAgICByZXR1cm4gZGVzdDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBzaW1wbGlmeTtcblxuLy8gY2FsY3VsYXRlIHNpbXBsaWZpY2F0aW9uIGRhdGEgdXNpbmcgb3B0aW1pemVkIERvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1cblxuZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcblxuICAgIHZhciBzcVRvbGVyYW5jZSA9IHRvbGVyYW5jZSAqIHRvbGVyYW5jZSxcbiAgICAgICAgbGVuID0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgZmlyc3QgPSAwLFxuICAgICAgICBsYXN0ID0gbGVuIC0gMSxcbiAgICAgICAgc3RhY2sgPSBbXSxcbiAgICAgICAgaSwgbWF4U3FEaXN0LCBzcURpc3QsIGluZGV4O1xuXG4gICAgLy8gYWx3YXlzIHJldGFpbiB0aGUgZW5kcG9pbnRzICgxIGlzIHRoZSBtYXggdmFsdWUpXG4gICAgcG9pbnRzW2ZpcnN0XVsyXSA9IDE7XG4gICAgcG9pbnRzW2xhc3RdWzJdID0gMTtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHN0YWNrXG4gICAgd2hpbGUgKGxhc3QpIHtcblxuICAgICAgICBtYXhTcURpc3QgPSAwO1xuXG4gICAgICAgIGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgc3FEaXN0ID0gZ2V0U3FTZWdEaXN0KHBvaW50c1tpXSwgcG9pbnRzW2ZpcnN0XSwgcG9pbnRzW2xhc3RdKTtcblxuICAgICAgICAgICAgaWYgKHNxRGlzdCA+IG1heFNxRGlzdCkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBtYXhTcURpc3QgPSBzcURpc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4U3FEaXN0ID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHBvaW50c1tpbmRleF1bMl0gPSBtYXhTcURpc3Q7IC8vIHNhdmUgdGhlIHBvaW50IGltcG9ydGFuY2UgaW4gc3F1YXJlZCBwaXhlbHMgYXMgYSB6IGNvb3JkaW5hdGVcbiAgICAgICAgICAgIHN0YWNrLnB1c2goZmlyc3QsIGluZGV4LCBpbmRleCwgbGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXN0ID0gc3RhY2sucG9wKCk7XG4gICAgICAgIGZpcnN0ID0gc3RhY2sucG9wKCk7XG4gICAgfVxufVxuXG4vLyBzcXVhcmUgZGlzdGFuY2UgZnJvbSBhIHBvaW50IHRvIGEgc2VnbWVudFxuZnVuY3Rpb24gZ2V0U3FTZWdEaXN0KHAsIGEsIGIpIHtcblxuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sXG4gICAgICAgIGJ4ID0gYlswXSwgYnkgPSBiWzFdLFxuICAgICAgICBweCA9IHBbMF0sIHB5ID0gcFsxXSxcbiAgICAgICAgZHggPSBieCAtIHgsXG4gICAgICAgIGR5ID0gYnkgLSB5O1xuXG4gICAgaWYgKGR4ICE9PSAwIHx8IGR5ICE9PSAwKSB7XG5cbiAgICAgICAgdmFyIHQgPSAoKHB4IC0geCkgKiBkeCArIChweSAtIHkpICogZHkpIC8gKGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZiAodCA+IDEpIHtcbiAgICAgICAgICAgIHggPSBieDtcbiAgICAgICAgICAgIHkgPSBieTtcblxuICAgICAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICAgICAgICB4ICs9IGR4ICogdDtcbiAgICAgICAgICAgIHkgKz0gZHkgKiB0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHggPSBweCAtIHg7XG4gICAgZHkgPSBweSAtIHk7XG5cbiAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGlsZTtcblxuZnVuY3Rpb24gY3JlYXRlVGlsZShmZWF0dXJlcywgejIsIHR4LCB0eSwgdG9sZXJhbmNlLCBleHRlbnQsIG5vU2ltcGxpZnkpIHtcbiAgICB2YXIgdGlsZSA9IHtcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgICBudW1Qb2ludHM6IDAsXG4gICAgICAgIG51bVNpbXBsaWZpZWQ6IDAsXG4gICAgICAgIG51bUZlYXR1cmVzOiAwLFxuICAgICAgICBzb3VyY2U6IG51bGxcbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGlsZS5udW1GZWF0dXJlcysrO1xuICAgICAgICBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmVzW2ldLCB6MiwgdHgsIHR5LCB0b2xlcmFuY2UsIGV4dGVudCwgbm9TaW1wbGlmeSk7XG4gICAgfVxuICAgIHJldHVybiB0aWxlO1xufVxuXG5mdW5jdGlvbiBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmUsIHoyLCB0eCwgdHksIHRvbGVyYW5jZSwgZXh0ZW50LCBub1NpbXBsaWZ5KSB7XG5cbiAgICB2YXIgZ2VvbSA9IGZlYXR1cmUuZ2VvbWV0cnksXG4gICAgICAgIHR5cGUgPSBmZWF0dXJlLnR5cGUsXG4gICAgICAgIHRyYW5zZm9ybWVkID0gW10sXG4gICAgICAgIHNxVG9sZXJhbmNlID0gdG9sZXJhbmNlICogdG9sZXJhbmNlLFxuICAgICAgICBpLCBqLCByaW5nLCBwO1xuXG4gICAgaWYgKHR5cGUgPT09IDEpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWVkLnB1c2godHJhbnNmb3JtUG9pbnQoZ2VvbVtpXSwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgdGlsZS5udW1TaW1wbGlmaWVkKys7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gc2ltcGxpZnkgYW5kIHRyYW5zZm9ybSBwcm9qZWN0ZWQgY29vcmRpbmF0ZXMgZm9yIHRpbGUgZ2VvbWV0cnlcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmcgPSBnZW9tW2ldO1xuXG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHRpbnkgcG9seWxpbmVzICYgcG9seWdvbnNcbiAgICAgICAgICAgIGlmICghbm9TaW1wbGlmeSAmJiAoKHR5cGUgPT09IDIgJiYgcmluZy5kaXN0IDwgdG9sZXJhbmNlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodHlwZSA9PT0gMyAmJiByaW5nLmFyZWEgPCBzcVRvbGVyYW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgdGlsZS5udW1Qb2ludHMgKz0gcmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZFJpbmcgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcmluZ1tqXTtcbiAgICAgICAgICAgICAgICAvLyBrZWVwIHBvaW50cyB3aXRoIGltcG9ydGFuY2UgPiB0b2xlcmFuY2VcbiAgICAgICAgICAgICAgICBpZiAobm9TaW1wbGlmeSB8fCBwWzJdID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRSaW5nLnB1c2godHJhbnNmb3JtUG9pbnQocCwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICAgICAgICAgIHRpbGUubnVtU2ltcGxpZmllZCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cmFuc2Zvcm1lZC5wdXNoKHRyYW5zZm9ybWVkUmluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNmb3JtZWQubGVuZ3RoKSB7XG4gICAgICAgIHRpbGUuZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICBnZW9tZXRyeTogdHJhbnNmb3JtZWQsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgdGFnczogZmVhdHVyZS50YWdzIHx8IG51bGxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludChwLCB6MiwgdHgsIHR5LCBleHRlbnQpIHtcbiAgICB2YXIgeCA9IE1hdGgucm91bmQoZXh0ZW50ICogKHBbMF0gKiB6MiAtIHR4KSksXG4gICAgICAgIHkgPSBNYXRoLnJvdW5kKGV4dGVudCAqIChwWzFdICogejIgLSB0eSkpO1xuICAgIHJldHVybiBbeCwgeV07XG59XG4iLCIvKipcbiAqIEBmaWxlb3ZlcnZpZXcgZ2wtbWF0cml4IC0gSGlnaCBwZXJmb3JtYW5jZSBtYXRyaXggYW5kIHZlY3RvciBvcGVyYXRpb25zXG4gKiBAYXV0aG9yIEJyYW5kb24gSm9uZXNcbiAqIEBhdXRob3IgQ29saW4gTWFjS2VuemllIElWXG4gKiBAdmVyc2lvbiAyLjIuMVxuICovXG5cbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbihmdW5jdGlvbihfZ2xvYmFsKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIHZhciBzaGltID0ge307XG4gIGlmICh0eXBlb2YoZXhwb3J0cykgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHt9O1xuICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gc2hpbS5leHBvcnRzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBhIGJyb3dzZXIsIGRlZmluZSBpdHMgbmFtZXNwYWNlcyBpbiBnbG9iYWxcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHR5cGVvZih3aW5kb3cpICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IF9nbG9iYWw7XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBjb21tb25qcywgZGVmaW5lIGl0cyBuYW1lc3BhY2VzIGluIGV4cG9ydHNcbiAgICBzaGltLmV4cG9ydHMgPSBleHBvcnRzO1xuICB9XG5cbiAgKGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAvKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbmlmKCFHTE1BVF9FUFNJTE9OKSB7XG4gICAgdmFyIEdMTUFUX0VQU0lMT04gPSAwLjAwMDAwMTtcbn1cblxuaWYoIUdMTUFUX0FSUkFZX1RZUEUpIHtcbiAgICB2YXIgR0xNQVRfQVJSQVlfVFlQRSA9ICh0eXBlb2YgRmxvYXQzMkFycmF5ICE9PSAndW5kZWZpbmVkJykgPyBGbG9hdDMyQXJyYXkgOiBBcnJheTtcbn1cblxuaWYoIUdMTUFUX1JBTkRPTSkge1xuICAgIHZhciBHTE1BVF9SQU5ET00gPSBNYXRoLnJhbmRvbTtcbn1cblxuLyoqXG4gKiBAY2xhc3MgQ29tbW9uIHV0aWxpdGllc1xuICogQG5hbWUgZ2xNYXRyaXhcbiAqL1xudmFyIGdsTWF0cml4ID0ge307XG5cbi8qKlxuICogU2V0cyB0aGUgdHlwZSBvZiBhcnJheSB1c2VkIHdoZW4gY3JlYXRpbmcgbmV3IHZlY3RvcnMgYW5kIG1hdHJpY2llc1xuICpcbiAqIEBwYXJhbSB7VHlwZX0gdHlwZSBBcnJheSB0eXBlLCBzdWNoIGFzIEZsb2F0MzJBcnJheSBvciBBcnJheVxuICovXG5nbE1hdHJpeC5zZXRNYXRyaXhBcnJheVR5cGUgPSBmdW5jdGlvbih0eXBlKSB7XG4gICAgR0xNQVRfQVJSQVlfVFlQRSA9IHR5cGU7XG59XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLmdsTWF0cml4ID0gZ2xNYXRyaXg7XG59XG5cbnZhciBkZWdyZWUgPSBNYXRoLlBJIC8gMTgwO1xuXG4vKipcbiogQ29udmVydCBEZWdyZWUgVG8gUmFkaWFuXG4qXG4qIEBwYXJhbSB7TnVtYmVyfSBBbmdsZSBpbiBEZWdyZWVzXG4qL1xuZ2xNYXRyaXgudG9SYWRpYW4gPSBmdW5jdGlvbihhKXtcbiAgICAgcmV0dXJuIGEgKiBkZWdyZWU7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyIERpbWVuc2lvbmFsIFZlY3RvclxuICogQG5hbWUgdmVjMlxuICovXG5cbnZhciB2ZWMyID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldywgZW1wdHkgdmVjMlxuICpcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gMDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgyKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzIgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHkpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLmFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnN1YnRyYWN0ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAtIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnN1YnRyYWN0fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuc3ViID0gdmVjMi5zdWJ0cmFjdDtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICogYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5tdWwgPSB2ZWMyLm11bHRpcGx5O1xuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5kaXZpZGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC8gYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdIC8gYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIuZGl2aWRlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGl2ID0gdmVjMi5kaXZpZGU7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWluaW11bSBvZiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLm1pbiA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pO1xuICAgIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5tYXggPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1heChhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgYSB2ZWMyIGJ5IGEgc2NhbGFyIG51bWJlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiO1xuICAgIG91dFsxXSA9IGFbMV0gKiBiO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzIncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnNjYWxlQW5kQWRkID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBzY2FsZSkge1xuICAgIG91dFswXSA9IGFbMF0gKyAoYlswXSAqIHNjYWxlKTtcbiAgICBvdXRbMV0gPSBhWzFdICsgKGJbMV0gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzIuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdO1xuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5KTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLmRpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGlzdCA9IHZlYzIuZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG52ZWMyLnNxdWFyZWREaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLnNxckRpc3QgPSB2ZWMyLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMyLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMi5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5sZW4gPSB2ZWMyLmxlbmd0aDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG52ZWMyLnNxdWFyZWRMZW5ndGggPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5zcXJMZW4gPSB2ZWMyLnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMyLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV07XG59O1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMyJ3NcbiAqIE5vdGUgdGhhdCB0aGUgY3Jvc3MgcHJvZHVjdCBtdXN0IGJ5IGRlZmluaXRpb24gcHJvZHVjZSBhIDNEIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMi5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciB6ID0gYVswXSAqIGJbMV0gLSBhWzFdICogYlswXTtcbiAgICBvdXRbMF0gPSBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IHo7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV07XG4gICAgb3V0WzBdID0gYXggKyB0ICogKGJbMF0gLSBheCk7XG4gICAgb3V0WzFdID0gYXkgKyB0ICogKGJbMV0gLSBheSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5yYW5kb20gPSBmdW5jdGlvbiAob3V0LCBzY2FsZSkge1xuICAgIHNjYWxlID0gc2NhbGUgfHwgMS4wO1xuICAgIHZhciByID0gR0xNQVRfUkFORE9NKCkgKiAyLjAgKiBNYXRoLlBJO1xuICAgIG91dFswXSA9IE1hdGguY29zKHIpICogc2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiBzY2FsZTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQyfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDIgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHk7XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzNdICogeTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyZFxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0MmR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIudHJhbnNmb3JtTWF0MmQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDNcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzEnXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQzfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDMgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVszXSAqIHkgKyBtWzZdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs0XSAqIHkgKyBtWzddO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDRcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzAnXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCBcbiAgICAgICAgeSA9IGFbMV07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bMTJdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzEzXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjMnMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMi4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzJzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzIuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gdmVjIHZlY3RvciB0byByZXByZXNlbnQgYXMgYSBzdHJpbmdcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmVjdG9yXG4gKi9cbnZlYzIuc3RyID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gJ3ZlYzIoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzIgPSB2ZWMyO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgMyBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzNcbiAqL1xuXG52YXIgdmVjMyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbnZlYzMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDMpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMyBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMyk7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgzKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjMyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzIHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnNldCA9IGZ1bmN0aW9uKG91dCwgeCwgeSwgeikge1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnN1YiA9IHZlYzMuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubXVsID0gdmVjMy5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpdiA9IHZlYzMuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5kaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeik7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpc3QgPSB2ZWMzLmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl07XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqejtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckRpc3QgPSB2ZWMzLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMzLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl07XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnopO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubGVuID0gdmVjMy5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjMy5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMuc3F1YXJlZExlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckxlbiA9IHZlYzMuc3F1YXJlZExlbmd0aDtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm5lZ2F0ZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IC1hWzBdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5ub3JtYWxpemUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5ICsgeip6O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMzLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTtcbn07XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdO1xuXG4gICAgb3V0WzBdID0gYXkgKiBieiAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV0sXG4gICAgICAgIGF6ID0gYVsyXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICB2YXIgciA9IEdMTUFUX1JBTkRPTSgpICogMi4wICogTWF0aC5QSTtcbiAgICB2YXIgeiA9IChHTE1BVF9SQU5ET00oKSAqIDIuMCkgLSAxLjA7XG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlO1xuXG4gICAgb3V0WzBdID0gTWF0aC5jb3MocikgKiB6U2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiB6U2NhbGU7XG4gICAgb3V0WzJdID0geiAqIHNjYWxlO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl07XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM107XG4gICAgb3V0WzJdID0gbVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMudHJhbnNmb3JtTWF0MyA9IGZ1bmN0aW9uKG91dCwgYSwgbSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdO1xuICAgIG91dFswXSA9IHggKiBtWzBdICsgeSAqIG1bM10gKyB6ICogbVs2XTtcbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN107XG4gICAgb3V0WzJdID0geCAqIG1bMl0gKyB5ICogbVs1XSArIHogKiBtWzhdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnRyYW5zZm9ybVF1YXQgPSBmdW5jdGlvbihvdXQsIGEsIHEpIHtcbiAgICAvLyBiZW5jaG1hcmtzOiBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXRyYW5zZm9ybS12ZWMzLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl0sXG4gICAgICAgIHF4ID0gcVswXSwgcXkgPSBxWzFdLCBxeiA9IHFbMl0sIHF3ID0gcVszXSxcblxuICAgICAgICAvLyBjYWxjdWxhdGUgcXVhdCAqIHZlY1xuICAgICAgICBpeCA9IHF3ICogeCArIHF5ICogeiAtIHF6ICogeSxcbiAgICAgICAgaXkgPSBxdyAqIHkgKyBxeiAqIHggLSBxeCAqIHosXG4gICAgICAgIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4LFxuICAgICAgICBpdyA9IC1xeCAqIHggLSBxeSAqIHkgLSBxeiAqIHo7XG5cbiAgICAvLyBjYWxjdWxhdGUgcmVzdWx0ICogaW52ZXJzZSBxdWF0XG4gICAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeTtcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6O1xuICAgIG91dFsyXSA9IGl6ICogcXcgKyBpdyAqIC1xeiArIGl4ICogLXF5IC0gaXkgKiAtcXg7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHgtYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVggPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICAgdmFyIHAgPSBbXSwgcj1bXTtcblx0ICAvL1RyYW5zbGF0ZSBwb2ludCB0byB0aGUgb3JpZ2luXG5cdCAgcFswXSA9IGFbMF0gLSBiWzBdO1xuXHQgIHBbMV0gPSBhWzFdIC0gYlsxXTtcbiAgXHRwWzJdID0gYVsyXSAtIGJbMl07XG5cblx0ICAvL3BlcmZvcm0gcm90YXRpb25cblx0ICByWzBdID0gcFswXTtcblx0ICByWzFdID0gcFsxXSpNYXRoLmNvcyhjKSAtIHBbMl0qTWF0aC5zaW4oYyk7XG5cdCAgclsyXSA9IHBbMV0qTWF0aC5zaW4oYykgKyBwWzJdKk1hdGguY29zKGMpO1xuXG5cdCAgLy90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuXHQgIG91dFswXSA9IHJbMF0gKyBiWzBdO1xuXHQgIG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuXHQgIG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuXG4gIFx0cmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHktYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVkgPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICBcdHZhciBwID0gW10sIHI9W107XG4gIFx0Ly9UcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICBcdHBbMF0gPSBhWzBdIC0gYlswXTtcbiAgXHRwWzFdID0gYVsxXSAtIGJbMV07XG4gIFx0cFsyXSA9IGFbMl0gLSBiWzJdO1xuICBcbiAgXHQvL3BlcmZvcm0gcm90YXRpb25cbiAgXHRyWzBdID0gcFsyXSpNYXRoLnNpbihjKSArIHBbMF0qTWF0aC5jb3MoYyk7XG4gIFx0clsxXSA9IHBbMV07XG4gIFx0clsyXSA9IHBbMl0qTWF0aC5jb3MoYykgLSBwWzBdKk1hdGguc2luKGMpO1xuICBcbiAgXHQvL3RyYW5zbGF0ZSB0byBjb3JyZWN0IHBvc2l0aW9uXG4gIFx0b3V0WzBdID0gclswXSArIGJbMF07XG4gIFx0b3V0WzFdID0gclsxXSArIGJbMV07XG4gIFx0b3V0WzJdID0gclsyXSArIGJbMl07XG4gIFxuICBcdHJldHVybiBvdXQ7XG59O1xuXG4vKlxuKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB6LWF4aXNcbiogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4qIEBwYXJhbSB7dmVjM30gYSBUaGUgdmVjMyBwb2ludCB0byByb3RhdGVcbiogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4qIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuKiBAcmV0dXJucyB7dmVjM30gb3V0XG4qL1xudmVjMy5yb3RhdGVaID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBjKXtcbiAgXHR2YXIgcCA9IFtdLCByPVtdO1xuICBcdC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgXHRwWzBdID0gYVswXSAtIGJbMF07XG4gIFx0cFsxXSA9IGFbMV0gLSBiWzFdO1xuICBcdHBbMl0gPSBhWzJdIC0gYlsyXTtcbiAgXG4gIFx0Ly9wZXJmb3JtIHJvdGF0aW9uXG4gIFx0clswXSA9IHBbMF0qTWF0aC5jb3MoYykgLSBwWzFdKk1hdGguc2luKGMpO1xuICBcdHJbMV0gPSBwWzBdKk1hdGguc2luKGMpICsgcFsxXSpNYXRoLmNvcyhjKTtcbiAgXHRyWzJdID0gcFsyXTtcbiAgXG4gIFx0Ly90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuICBcdG91dFswXSA9IHJbMF0gKyBiWzBdO1xuICBcdG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuICBcdG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuICBcbiAgXHRyZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjM3MuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMy4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzNzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzMuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07IHZlY1syXSA9IGFbaSsyXTtcbiAgICAgICAgICAgIGZuKHZlYywgdmVjLCBhcmcpO1xuICAgICAgICAgICAgYVtpXSA9IHZlY1swXTsgYVtpKzFdID0gdmVjWzFdOyBhW2krMl0gPSB2ZWNbMl07XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWMzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWMzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzMgPSB2ZWMzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNCBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzRcbiAqL1xuXG52YXIgdmVjNCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbnZlYzQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWM0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmZyb21WYWx1ZXMgPSBmdW5jdGlvbih4LCB5LCB6LCB3KSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIG91dFszXSA9IHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHksIHosIHcpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSB3O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICBvdXRbM10gPSBhWzNdICsgYlszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIG91dFszXSA9IGFbM10gLSBiWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LnN1YiA9IHZlYzQuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0Lm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAqIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubXVsID0gdmVjNC5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAvIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpdiA9IHZlYzQuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICBvdXRbM10gPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICBvdXRbM10gPSBhWzNdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICBvdXRbM10gPSBhWzNdICsgKGJbM10gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzQuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeiArIHcqdyk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpc3QgPSB2ZWM0LmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjNC5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6ICsgdyp3O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3F1YXJlZERpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuc3FyRGlzdCA9IHZlYzQuc3F1YXJlZERpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbnZlYzQubGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnogKyB3KncpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubGVuID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjNC5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqeiArIHcqdztcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjNC5zcXJMZW4gPSB2ZWM0LnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICBvdXRbMl0gPSAtYVsyXTtcbiAgICBvdXRbM10gPSAtYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl0sXG4gICAgICAgIHcgPSBhWzNdO1xuICAgIHZhciBsZW4gPSB4KnggKyB5KnkgKyB6KnogKyB3Knc7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pO1xuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuO1xuICAgICAgICBvdXRbMV0gPSBhWzFdICogbGVuO1xuICAgICAgICBvdXRbMl0gPSBhWzJdICogbGVuO1xuICAgICAgICBvdXRbM10gPSBhWzNdICogbGVuO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbnZlYzQuZG90ID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM107XG59O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LmxlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl0sXG4gICAgICAgIGF3ID0gYVszXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICAvL1RPRE86IFRoaXMgaXMgYSBwcmV0dHkgYXdmdWwgd2F5IG9mIGRvaW5nIHRoaXMuIEZpbmQgc29tZXRoaW5nIGJldHRlci5cbiAgICBvdXRbMF0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMV0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMl0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbM10gPSBHTE1BVF9SQU5ET00oKTtcbiAgICB2ZWM0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgdmVjNC5zY2FsZShvdXQsIG91dCwgc2NhbGUpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzQgd2l0aCBhIG1hdDQuXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnRyYW5zZm9ybU1hdDQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM107XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogdztcbiAgICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3O1xuICAgIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7cXVhdH0gcSBxdWF0ZXJuaW9uIHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQudHJhbnNmb3JtUXVhdCA9IGZ1bmN0aW9uKG91dCwgYSwgcSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLFxuICAgICAgICBxeCA9IHFbMF0sIHF5ID0gcVsxXSwgcXogPSBxWzJdLCBxdyA9IHFbM10sXG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHF1YXQgKiB2ZWNcbiAgICAgICAgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHksXG4gICAgICAgIGl5ID0gcXcgKiB5ICsgcXogKiB4IC0gcXggKiB6LFxuICAgICAgICBpeiA9IHF3ICogeiArIHF4ICogeSAtIHF5ICogeCxcbiAgICAgICAgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6O1xuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXk7XG4gICAgb3V0WzFdID0gaXkgKiBxdyArIGl3ICogLXF5ICsgaXogKiAtcXggLSBpeCAqIC1xejtcbiAgICBvdXRbMl0gPSBpeiAqIHF3ICsgaXcgKiAtcXogKyBpeCAqIC1xeSAtIGl5ICogLXF4O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFBlcmZvcm0gc29tZSBvcGVyYXRpb24gb3ZlciBhbiBhcnJheSBvZiB2ZWM0cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhIHRoZSBhcnJheSBvZiB2ZWN0b3JzIHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIHtOdW1iZXJ9IHN0cmlkZSBOdW1iZXIgb2YgZWxlbWVudHMgYmV0d2VlbiB0aGUgc3RhcnQgb2YgZWFjaCB2ZWM0LiBJZiAwIGFzc3VtZXMgdGlnaHRseSBwYWNrZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXQgTnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNraXAgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudCBOdW1iZXIgb2YgdmVjMnMgdG8gaXRlcmF0ZSBvdmVyLiBJZiAwIGl0ZXJhdGVzIG92ZXIgZW50aXJlIGFycmF5XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbYXJnXSBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHBhc3MgdG8gZm5cbiAqIEByZXR1cm5zIHtBcnJheX0gYVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuZm9yRWFjaCA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdmVjID0gdmVjNC5jcmVhdGUoKTtcblxuICAgIHJldHVybiBmdW5jdGlvbihhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGlmKCFzdHJpZGUpIHtcbiAgICAgICAgICAgIHN0cmlkZSA9IDQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZighb2Zmc2V0KSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGwgPSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gb2Zmc2V0OyBpIDwgbDsgaSArPSBzdHJpZGUpIHtcbiAgICAgICAgICAgIHZlY1swXSA9IGFbaV07IHZlY1sxXSA9IGFbaSsxXTsgdmVjWzJdID0gYVtpKzJdOyB2ZWNbM10gPSBhW2krM107XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTsgYVtpKzJdID0gdmVjWzJdOyBhW2krM10gPSB2ZWNbM107XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWM0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWM0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMudmVjNCA9IHZlYzQ7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDIgTWF0cml4XG4gKiBAbmFtZSBtYXQyXG4gKi9cblxudmFyIG1hdDIgPSB7fTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGlkZW50aXR5IG1hdDJcbiAqXG4gKiBAcmV0dXJucyB7bWF0Mn0gYSBuZXcgMngyIG1hdHJpeFxuICovXG5tYXQyLmNyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSAxO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSBtYXRyaXggdG8gY2xvbmVcbiAqIEByZXR1cm5zIHttYXQyfSBhIG5ldyAyeDIgbWF0cml4XG4gKi9cbm1hdDIuY2xvbmUgPSBmdW5jdGlvbihhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqL1xubWF0Mi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQyIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGExID0gYVsxXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYVsxXTtcbiAgICAgICAgb3V0WzNdID0gYVszXTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGEwICogYTMgLSBhMiAqIGExO1xuXG4gICAgaWYgKCFkZXQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcbiAgICBcbiAgICBvdXRbMF0gPSAgYTMgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWExICogZGV0O1xuICAgIG91dFsyXSA9IC1hMiAqIGRldDtcbiAgICBvdXRbM10gPSAgYTAgKiBkZXQ7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhZGp1Z2F0ZSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuYWRqb2ludCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIENhY2hpbmcgdGhpcyB2YWx1ZSBpcyBuZXNzZWNhcnkgaWYgb3V0ID09IGFcbiAgICB2YXIgYTAgPSBhWzBdO1xuICAgIG91dFswXSA9ICBhWzNdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIG91dFszXSA9ICBhMDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MlxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQyLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzJdICogYVsxXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MidzXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM107XG4gICAgdmFyIGIwID0gYlswXSwgYjEgPSBiWzFdLCBiMiA9IGJbMl0sIGIzID0gYlszXTtcbiAgICBvdXRbMF0gPSBhMCAqIGIwICsgYTIgKiBiMTtcbiAgICBvdXRbMV0gPSBhMSAqIGIwICsgYTMgKiBiMTtcbiAgICBvdXRbMl0gPSBhMCAqIGIyICsgYTIgKiBiMztcbiAgICBvdXRbM10gPSBhMSAqIGIyICsgYTMgKiBiMztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0Mi5tdWwgPSBtYXQyLm11bHRpcGx5O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQyIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIucm90YXRlID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICAgIG91dFswXSA9IGEwICogIGMgKyBhMiAqIHM7XG4gICAgb3V0WzFdID0gYTEgKiAgYyArIGEzICogcztcbiAgICBvdXRbMl0gPSBhMCAqIC1zICsgYTIgKiBjO1xuICAgIG91dFszXSA9IGExICogLXMgKyBhMyAqIGM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQyIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMyfSB2IHRoZSB2ZWMyIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqKi9cbm1hdDIuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIHYpIHtcbiAgICB2YXIgYTAgPSBhWzBdLCBhMSA9IGFbMV0sIGEyID0gYVsyXSwgYTMgPSBhWzNdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMCAqIHYwO1xuICAgIG91dFsxXSA9IGExICogdjA7XG4gICAgb3V0WzJdID0gYTIgKiB2MTtcbiAgICBvdXRbM10gPSBhMyAqIHYxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQyXG4gKlxuICogQHBhcmFtIHttYXQyfSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0Mi5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MignICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byBjYWxjdWxhdGUgRnJvYmVuaXVzIG5vcm0gb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IEZyb2Jlbml1cyBub3JtXG4gKi9cbm1hdDIuZnJvYiA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuKE1hdGguc3FydChNYXRoLnBvdyhhWzBdLCAyKSArIE1hdGgucG93KGFbMV0sIDIpICsgTWF0aC5wb3coYVsyXSwgMikgKyBNYXRoLnBvdyhhWzNdLCAyKSkpXG59O1xuXG4vKipcbiAqIFJldHVybnMgTCwgRCBhbmQgVSBtYXRyaWNlcyAoTG93ZXIgdHJpYW5ndWxhciwgRGlhZ29uYWwgYW5kIFVwcGVyIHRyaWFuZ3VsYXIpIGJ5IGZhY3Rvcml6aW5nIHRoZSBpbnB1dCBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gTCB0aGUgbG93ZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IEQgdGhlIGRpYWdvbmFsIG1hdHJpeCBcbiAqIEBwYXJhbSB7bWF0Mn0gVSB0aGUgdXBwZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIGlucHV0IG1hdHJpeCB0byBmYWN0b3JpemVcbiAqL1xuXG5tYXQyLkxEVSA9IGZ1bmN0aW9uIChMLCBELCBVLCBhKSB7IFxuICAgIExbMl0gPSBhWzJdL2FbMF07IFxuICAgIFVbMF0gPSBhWzBdOyBcbiAgICBVWzFdID0gYVsxXTsgXG4gICAgVVszXSA9IGFbM10gLSBMWzJdICogVVsxXTsgXG4gICAgcmV0dXJuIFtMLCBELCBVXTsgICAgICAgXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MiA9IG1hdDI7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDMgTWF0cml4XG4gKiBAbmFtZSBtYXQyZFxuICogXG4gKiBAZGVzY3JpcHRpb24gXG4gKiBBIG1hdDJkIGNvbnRhaW5zIHNpeCBlbGVtZW50cyBkZWZpbmVkIGFzOlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eV1cbiAqIDwvcHJlPlxuICogVGhpcyBpcyBhIHNob3J0IGZvcm0gZm9yIHRoZSAzeDMgbWF0cml4OlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eSxcbiAqICAwLCAwLCAxXVxuICogPC9wcmU+XG4gKiBUaGUgbGFzdCByb3cgaXMgaWdub3JlZCBzbyB0aGUgYXJyYXkgaXMgc2hvcnRlciBhbmQgb3BlcmF0aW9ucyBhcmUgZmFzdGVyLlxuICovXG5cbnZhciBtYXQyZCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0MmRcbiAqXG4gKiBAcmV0dXJucyB7bWF0MmR9IGEgbmV3IDJ4MyBtYXRyaXhcbiAqL1xubWF0MmQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MmQgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDJkfSBhIG5ldyAyeDMgbWF0cml4XG4gKi9cbm1hdDJkLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg2KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MmQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqL1xubWF0MmQuY29weSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCBhIG1hdDJkIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0MmR9IG91dFxuICovXG5tYXQyZC5pbnZlcnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYWEgPSBhWzBdLCBhYiA9IGFbMV0sIGFjID0gYVsyXSwgYWQgPSBhWzNdLFxuICAgICAgICBhdHggPSBhWzRdLCBhdHkgPSBhWzVdO1xuXG4gICAgdmFyIGRldCA9IGFhICogYWQgLSBhYiAqIGFjO1xuICAgIGlmKCFkZXQpe1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYWQgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWFiICogZGV0O1xuICAgIG91dFsyXSA9IC1hYyAqIGRldDtcbiAgICBvdXRbM10gPSBhYSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYWMgKiBhdHkgLSBhZCAqIGF0eCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKGFiICogYXR4IC0gYWEgKiBhdHkpICogZGV0O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MmRcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDJkLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzFdICogYVsyXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MmQnc1xuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyZH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBiMCA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM10sIGI0ID0gYls0XSwgYjUgPSBiWzVdO1xuICAgIG91dFswXSA9IGEwICogYjAgKyBhMiAqIGIxO1xuICAgIG91dFsxXSA9IGExICogYjAgKyBhMyAqIGIxO1xuICAgIG91dFsyXSA9IGEwICogYjIgKyBhMiAqIGIzO1xuICAgIG91dFszXSA9IGExICogYjIgKyBhMyAqIGIzO1xuICAgIG91dFs0XSA9IGEwICogYjQgKyBhMiAqIGI1ICsgYTQ7XG4gICAgb3V0WzVdID0gYTEgKiBiNCArIGEzICogYjUgKyBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDJkLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDJkLm11bCA9IG1hdDJkLm11bHRpcGx5O1xuXG5cbi8qKlxuICogUm90YXRlcyBhIG1hdDJkIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgb3V0WzBdID0gYTAgKiAgYyArIGEyICogcztcbiAgICBvdXRbMV0gPSBhMSAqICBjICsgYTMgKiBzO1xuICAgIG91dFsyXSA9IGEwICogLXMgKyBhMiAqIGM7XG4gICAgb3V0WzNdID0gYTEgKiAtcyArIGEzICogYztcbiAgICBvdXRbNF0gPSBhNDtcbiAgICBvdXRbNV0gPSBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDJkIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnNjYWxlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSwgYTQgPSBhWzRdLCBhNSA9IGFbNV0sXG4gICAgICAgIHYwID0gdlswXSwgdjEgPSB2WzFdO1xuICAgIG91dFswXSA9IGEwICogdjA7XG4gICAgb3V0WzFdID0gYTEgKiB2MDtcbiAgICBvdXRbMl0gPSBhMiAqIHYxO1xuICAgIG91dFszXSA9IGEzICogdjE7XG4gICAgb3V0WzRdID0gYTQ7XG4gICAgb3V0WzVdID0gYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNsYXRlcyB0aGUgbWF0MmQgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB0aGUgdmVjMiB0byB0cmFuc2xhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMDtcbiAgICBvdXRbMV0gPSBhMTtcbiAgICBvdXRbMl0gPSBhMjtcbiAgICBvdXRbM10gPSBhMztcbiAgICBvdXRbNF0gPSBhMCAqIHYwICsgYTIgKiB2MSArIGE0O1xuICAgIG91dFs1XSA9IGExICogdjAgKyBhMyAqIHYxICsgYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQyZC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MmQoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcsICcgKyBhWzJdICsgJywgJyArIFxuICAgICAgICAgICAgICAgICAgICBhWzNdICsgJywgJyArIGFbNF0gKyAnLCAnICsgYVs1XSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0MmQuZnJvYiA9IGZ1bmN0aW9uIChhKSB7IFxuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgMSkpXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MmQgPSBtYXQyZDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIDN4MyBNYXRyaXhcbiAqIEBuYW1lIG1hdDNcbiAqL1xuXG52YXIgbWF0MyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0M1xuICpcbiAqIEByZXR1cm5zIHttYXQzfSBhIG5ldyAzeDMgbWF0cml4XG4gKi9cbm1hdDMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDkpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMTtcbiAgICBvdXRbNV0gPSAwO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENvcGllcyB0aGUgdXBwZXItbGVmdCAzeDMgdmFsdWVzIGludG8gdGhlIGdpdmVuIG1hdDMuXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyAzeDMgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgICB0aGUgc291cmNlIDR4NCBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xubWF0My5mcm9tTWF0NCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbNF07XG4gICAgb3V0WzRdID0gYVs1XTtcbiAgICBvdXRbNV0gPSBhWzZdO1xuICAgIG91dFs2XSA9IGFbOF07XG4gICAgb3V0WzddID0gYVs5XTtcbiAgICBvdXRbOF0gPSBhWzEwXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IG1hdDMgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IGEgbWF0cml4IHRvIGNsb25lXG4gKiBAcmV0dXJucyB7bWF0M30gYSBuZXcgM3gzIG1hdHJpeFxuICovXG5tYXQzLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg5KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQzIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAxO1xuICAgIG91dFs1XSA9IDA7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNwb3NlIHRoZSB2YWx1ZXMgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnRyYW5zcG9zZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgICBpZiAob3V0ID09PSBhKSB7XG4gICAgICAgIHZhciBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMTIgPSBhWzVdO1xuICAgICAgICBvdXRbMV0gPSBhWzNdO1xuICAgICAgICBvdXRbMl0gPSBhWzZdO1xuICAgICAgICBvdXRbM10gPSBhMDE7XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGEwMjtcbiAgICAgICAgb3V0WzddID0gYTEyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFswXSA9IGFbMF07XG4gICAgICAgIG91dFsxXSA9IGFbM107XG4gICAgICAgIG91dFsyXSA9IGFbNl07XG4gICAgICAgIG91dFszXSA9IGFbMV07XG4gICAgICAgIG91dFs0XSA9IGFbNF07XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGFbMl07XG4gICAgICAgIG91dFs3XSA9IGFbNV07XG4gICAgICAgIG91dFs4XSA9IGFbOF07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmludmVydCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIGIwMSA9IGEyMiAqIGExMSAtIGExMiAqIGEyMSxcbiAgICAgICAgYjExID0gLWEyMiAqIGExMCArIGExMiAqIGEyMCxcbiAgICAgICAgYjIxID0gYTIxICogYTEwIC0gYTExICogYTIwLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYjAxICogZGV0O1xuICAgIG91dFsxXSA9ICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldDtcbiAgICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldDtcbiAgICBvdXRbM10gPSBiMTEgKiBkZXQ7XG4gICAgb3V0WzRdID0gKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0O1xuICAgIG91dFs2XSA9IGIyMSAqIGRldDtcbiAgICBvdXRbN10gPSAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQ7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIG91dFswXSA9IChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpO1xuICAgIG91dFsxXSA9IChhMDIgKiBhMjEgLSBhMDEgKiBhMjIpO1xuICAgIG91dFsyXSA9IChhMDEgKiBhMTIgLSBhMDIgKiBhMTEpO1xuICAgIG91dFszXSA9IChhMTIgKiBhMjAgLSBhMTAgKiBhMjIpO1xuICAgIG91dFs0XSA9IChhMDAgKiBhMjIgLSBhMDIgKiBhMjApO1xuICAgIG91dFs1XSA9IChhMDIgKiBhMTAgLSBhMDAgKiBhMTIpO1xuICAgIG91dFs2XSA9IChhMTAgKiBhMjEgLSBhMTEgKiBhMjApO1xuICAgIG91dFs3XSA9IChhMDEgKiBhMjAgLSBhMDAgKiBhMjEpO1xuICAgIG91dFs4XSA9IChhMDAgKiBhMTEgLSBhMDEgKiBhMTApO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQzLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIHJldHVybiBhMDAgKiAoYTIyICogYTExIC0gYTEyICogYTIxKSArIGEwMSAqICgtYTIyICogYTEwICsgYTEyICogYTIwKSArIGEwMiAqIChhMjEgKiBhMTAgLSBhMTEgKiBhMjApO1xufTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQzJ3NcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge21hdDN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMubXVsdGlwbHkgPSBmdW5jdGlvbiAob3V0LCBhLCBiKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG5cbiAgICAgICAgYjAwID0gYlswXSwgYjAxID0gYlsxXSwgYjAyID0gYlsyXSxcbiAgICAgICAgYjEwID0gYlszXSwgYjExID0gYls0XSwgYjEyID0gYls1XSxcbiAgICAgICAgYjIwID0gYls2XSwgYjIxID0gYls3XSwgYjIyID0gYls4XTtcblxuICAgIG91dFswXSA9IGIwMCAqIGEwMCArIGIwMSAqIGExMCArIGIwMiAqIGEyMDtcbiAgICBvdXRbMV0gPSBiMDAgKiBhMDEgKyBiMDEgKiBhMTEgKyBiMDIgKiBhMjE7XG4gICAgb3V0WzJdID0gYjAwICogYTAyICsgYjAxICogYTEyICsgYjAyICogYTIyO1xuXG4gICAgb3V0WzNdID0gYjEwICogYTAwICsgYjExICogYTEwICsgYjEyICogYTIwO1xuICAgIG91dFs0XSA9IGIxMCAqIGEwMSArIGIxMSAqIGExMSArIGIxMiAqIGEyMTtcbiAgICBvdXRbNV0gPSBiMTAgKiBhMDIgKyBiMTEgKiBhMTIgKyBiMTIgKiBhMjI7XG5cbiAgICBvdXRbNl0gPSBiMjAgKiBhMDAgKyBiMjEgKiBhMTAgKyBiMjIgKiBhMjA7XG4gICAgb3V0WzddID0gYjIwICogYTAxICsgYjIxICogYTExICsgYjIyICogYTIxO1xuICAgIG91dFs4XSA9IGIyMCAqIGEwMiArIGIyMSAqIGExMiArIGIyMiAqIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDMubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0My5tdWwgPSBtYXQzLm11bHRpcGx5O1xuXG4vKipcbiAqIFRyYW5zbGF0ZSBhIG1hdDMgYnkgdGhlIGdpdmVuIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDN9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMudHJhbnNsYXRlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG4gICAgICAgIHggPSB2WzBdLCB5ID0gdlsxXTtcblxuICAgIG91dFswXSA9IGEwMDtcbiAgICBvdXRbMV0gPSBhMDE7XG4gICAgb3V0WzJdID0gYTAyO1xuXG4gICAgb3V0WzNdID0gYTEwO1xuICAgIG91dFs0XSA9IGExMTtcbiAgICBvdXRbNV0gPSBhMTI7XG5cbiAgICBvdXRbNl0gPSB4ICogYTAwICsgeSAqIGExMCArIGEyMDtcbiAgICBvdXRbN10gPSB4ICogYTAxICsgeSAqIGExMSArIGEyMTtcbiAgICBvdXRbOF0gPSB4ICogYTAyICsgeSAqIGExMiArIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0MyBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKTtcblxuICAgIG91dFswXSA9IGMgKiBhMDAgKyBzICogYTEwO1xuICAgIG91dFsxXSA9IGMgKiBhMDEgKyBzICogYTExO1xuICAgIG91dFsyXSA9IGMgKiBhMDIgKyBzICogYTEyO1xuXG4gICAgb3V0WzNdID0gYyAqIGExMCAtIHMgKiBhMDA7XG4gICAgb3V0WzRdID0gYyAqIGExMSAtIHMgKiBhMDE7XG4gICAgb3V0WzVdID0gYyAqIGExMiAtIHMgKiBhMDI7XG5cbiAgICBvdXRbNl0gPSBhMjA7XG4gICAgb3V0WzddID0gYTIxO1xuICAgIG91dFs4XSA9IGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDMgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICoqL1xubWF0My5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV07XG5cbiAgICBvdXRbMF0gPSB4ICogYVswXTtcbiAgICBvdXRbMV0gPSB4ICogYVsxXTtcbiAgICBvdXRbMl0gPSB4ICogYVsyXTtcblxuICAgIG91dFszXSA9IHkgKiBhWzNdO1xuICAgIG91dFs0XSA9IHkgKiBhWzRdO1xuICAgIG91dFs1XSA9IHkgKiBhWzVdO1xuXG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29waWVzIHRoZSB2YWx1ZXMgZnJvbSBhIG1hdDJkIGludG8gYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byBjb3B5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKiovXG5tYXQzLmZyb21NYXQyZCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSAwO1xuXG4gICAgb3V0WzNdID0gYVsyXTtcbiAgICBvdXRbNF0gPSBhWzNdO1xuICAgIG91dFs1XSA9IDA7XG5cbiAgICBvdXRbNl0gPSBhWzRdO1xuICAgIG91dFs3XSA9IGFbNV07XG4gICAgb3V0WzhdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbWF0cml4IGZyb20gdGhlIGdpdmVuIHF1YXRlcm5pb25cbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge3F1YXR9IHEgUXVhdGVybmlvbiB0byBjcmVhdGUgbWF0cml4IGZyb21cbipcbiogQHJldHVybnMge21hdDN9IG91dFxuKi9cbm1hdDMuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbM10gPSB5eCAtIHd6O1xuICAgIG91dFs2XSA9IHp4ICsgd3k7XG5cbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFs0XSA9IDEgLSB4eCAtIHp6O1xuICAgIG91dFs3XSA9IHp5IC0gd3g7XG5cbiAgICBvdXRbMl0gPSB6eCAtIHd5O1xuICAgIG91dFs1XSA9IHp5ICsgd3g7XG4gICAgb3V0WzhdID0gMSAtIHh4IC0geXk7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbm9ybWFsIG1hdHJpeCAodHJhbnNwb3NlIGludmVyc2UpIGZyb20gdGhlIDR4NCBtYXRyaXhcbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge21hdDR9IGEgTWF0NCB0byBkZXJpdmUgdGhlIG5vcm1hbCBtYXRyaXggZnJvbVxuKlxuKiBAcmV0dXJucyB7bWF0M30gb3V0XG4qL1xubWF0My5ub3JtYWxGcm9tTWF0NCA9IGZ1bmN0aW9uIChvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XSxcblxuICAgICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXG4gICAgICAgIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMCxcbiAgICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxuICAgICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXG4gICAgICAgIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMSxcbiAgICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxuICAgICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXG4gICAgICAgIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMCxcbiAgICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxuICAgICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXG4gICAgICAgIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMSxcbiAgICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzFdID0gKGExMiAqIGIwOCAtIGExMCAqIGIxMSAtIGExMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzJdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG5cbiAgICBvdXRbM10gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcblxuICAgIG91dFs2XSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFs3XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG1hdCBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdtYXQzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVszXSArICcsICcgKyBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgXG4gICAgICAgICAgICAgICAgICAgIGFbNl0gKyAnLCAnICsgYVs3XSArICcsICcgKyBhWzhdICsgJyknO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIEZyb2Jlbml1cyBub3JtIG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0My5mcm9iID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4oTWF0aC5zcXJ0KE1hdGgucG93KGFbMF0sIDIpICsgTWF0aC5wb3coYVsxXSwgMikgKyBNYXRoLnBvdyhhWzJdLCAyKSArIE1hdGgucG93KGFbM10sIDIpICsgTWF0aC5wb3coYVs0XSwgMikgKyBNYXRoLnBvdyhhWzVdLCAyKSArIE1hdGgucG93KGFbNl0sIDIpICsgTWF0aC5wb3coYVs3XSwgMikgKyBNYXRoLnBvdyhhWzhdLCAyKSkpXG59O1xuXG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLm1hdDMgPSBtYXQzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNHg0IE1hdHJpeFxuICogQG5hbWUgbWF0NFxuICovXG5cbnZhciBtYXQ0ID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBpZGVudGl0eSBtYXQ0XG4gKlxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQ0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIG91dFs2XSA9IGFbNl07XG4gICAgb3V0WzddID0gYVs3XTtcbiAgICBvdXRbOF0gPSBhWzhdO1xuICAgIG91dFs5XSA9IGFbOV07XG4gICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgIG91dFsxMV0gPSBhWzExXTtcbiAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbNF0gPSBhWzRdO1xuICAgIG91dFs1XSA9IGFbNV07XG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQ0IHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgICAgICBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGEwMTtcbiAgICAgICAgb3V0WzZdID0gYVs5XTtcbiAgICAgICAgb3V0WzddID0gYVsxM107XG4gICAgICAgIG91dFs4XSA9IGEwMjtcbiAgICAgICAgb3V0WzldID0gYTEyO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhMDM7XG4gICAgICAgIG91dFsxM10gPSBhMTM7XG4gICAgICAgIG91dFsxNF0gPSBhMjM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGFbMV07XG4gICAgICAgIG91dFs1XSA9IGFbNV07XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhWzJdO1xuICAgICAgICBvdXRbOV0gPSBhWzZdO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbM107XG4gICAgICAgIG91dFsxM10gPSBhWzddO1xuICAgICAgICBvdXRbMTRdID0gYVsxMV07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV0sXG5cbiAgICAgICAgYjAwID0gYTAwICogYTExIC0gYTAxICogYTEwLFxuICAgICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXG4gICAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcbiAgICAgICAgYjAzID0gYTAxICogYTEyIC0gYTAyICogYTExLFxuICAgICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXG4gICAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcbiAgICAgICAgYjA2ID0gYTIwICogYTMxIC0gYTIxICogYTMwLFxuICAgICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXG4gICAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcbiAgICAgICAgYjA5ID0gYTIxICogYTMyIC0gYTIyICogYTMxLFxuICAgICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXG4gICAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMixcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcblxuICAgIGlmICghZGV0KSB7IFxuICAgICAgICByZXR1cm4gbnVsbDsgXG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcblxuICAgIG91dFswXSA9IChhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDkpICogZGV0O1xuICAgIG91dFsxXSA9IChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0O1xuICAgIG91dFsyXSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFszXSA9IChhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMpICogZGV0O1xuICAgIG91dFs0XSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICAgIG91dFs1XSA9IChhMDAgKiBiMTEgLSBhMDIgKiBiMDggKyBhMDMgKiBiMDcpICogZGV0O1xuICAgIG91dFs2XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs3XSA9IChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMTAgKiBiMTAgLSBhMTEgKiBiMDggKyBhMTMgKiBiMDYpICogZGV0O1xuICAgIG91dFs5XSA9IChhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYpICogZGV0O1xuICAgIG91dFsxMF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTFdID0gKGEyMSAqIGIwMiAtIGEyMCAqIGIwNCAtIGEyMyAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzEyXSA9IChhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYpICogZGV0O1xuICAgIG91dFsxM10gPSAoYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTRdID0gKGEzMSAqIGIwMSAtIGEzMCAqIGIwMyAtIGEzMiAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzE1XSA9IChhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XTtcblxuICAgIG91dFswXSAgPSAgKGExMSAqIChhMjIgKiBhMzMgLSBhMjMgKiBhMzIpIC0gYTIxICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgKyBhMzEgKiAoYTEyICogYTIzIC0gYTEzICogYTIyKSk7XG4gICAgb3V0WzFdICA9IC0oYTAxICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjEgKiAoYTAyICogYTMzIC0gYTAzICogYTMyKSArIGEzMSAqIChhMDIgKiBhMjMgLSBhMDMgKiBhMjIpKTtcbiAgICBvdXRbMl0gID0gIChhMDEgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSAtIGExMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGExMyAtIGEwMyAqIGExMikpO1xuICAgIG91dFszXSAgPSAtKGEwMSAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpIC0gYTExICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikgKyBhMjEgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzRdICA9IC0oYTEwICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjAgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSArIGEzMCAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpKTtcbiAgICBvdXRbNV0gID0gIChhMDAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMwICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikpO1xuICAgIG91dFs2XSAgPSAtKGEwMCAqIChhMTIgKiBhMzMgLSBhMTMgKiBhMzIpIC0gYTEwICogKGEwMiAqIGEzMyAtIGEwMyAqIGEzMikgKyBhMzAgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzddICA9ICAoYTAwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTAgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgICBvdXRbOF0gID0gIChhMTAgKiAoYTIxICogYTMzIC0gYTIzICogYTMxKSAtIGEyMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpICsgYTMwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSkpO1xuICAgIG91dFs5XSAgPSAtKGEwMCAqIChhMjEgKiBhMzMgLSBhMjMgKiBhMzEpIC0gYTIwICogKGEwMSAqIGEzMyAtIGEwMyAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTIzIC0gYTAzICogYTIxKSk7XG4gICAgb3V0WzEwXSA9ICAoYTAwICogKGExMSAqIGEzMyAtIGExMyAqIGEzMSkgLSBhMTAgKiAoYTAxICogYTMzIC0gYTAzICogYTMxKSArIGEzMCAqIChhMDEgKiBhMTMgLSBhMDMgKiBhMTEpKTtcbiAgICBvdXRbMTFdID0gLShhMDAgKiAoYTExICogYTIzIC0gYTEzICogYTIxKSAtIGExMCAqIChhMDEgKiBhMjMgLSBhMDMgKiBhMjEpICsgYTIwICogKGEwMSAqIGExMyAtIGEwMyAqIGExMSkpO1xuICAgIG91dFsxMl0gPSAtKGExMCAqIChhMjEgKiBhMzIgLSBhMjIgKiBhMzEpIC0gYTIwICogKGExMSAqIGEzMiAtIGExMiAqIGEzMSkgKyBhMzAgKiAoYTExICogYTIyIC0gYTEyICogYTIxKSk7XG4gICAgb3V0WzEzXSA9ICAoYTAwICogKGEyMSAqIGEzMiAtIGEyMiAqIGEzMSkgLSBhMjAgKiAoYTAxICogYTMyIC0gYTAyICogYTMxKSArIGEzMCAqIChhMDEgKiBhMjIgLSBhMDIgKiBhMjEpKTtcbiAgICBvdXRbMTRdID0gLShhMDAgKiAoYTExICogYTMyIC0gYTEyICogYTMxKSAtIGExMCAqIChhMDEgKiBhMzIgLSBhMDIgKiBhMzEpICsgYTMwICogKGEwMSAqIGExMiAtIGEwMiAqIGExMSkpO1xuICAgIG91dFsxNV0gPSAgKGEwMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpIC0gYTEwICogKGEwMSAqIGEyMiAtIGEwMiAqIGEyMSkgKyBhMjAgKiAoYTAxICogYTEyIC0gYTAyICogYTExKSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZGV0ZXJtaW5hbnQgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDQuZGV0ZXJtaW5hbnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgcmV0dXJuIGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0NCdzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0Lm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdO1xuXG4gICAgLy8gQ2FjaGUgb25seSB0aGUgY3VycmVudCBsaW5lIG9mIHRoZSBzZWNvbmQgbWF0cml4XG4gICAgdmFyIGIwICA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107ICBcbiAgICBvdXRbMF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzFdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsyXSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbM10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbNF07IGIxID0gYls1XTsgYjIgPSBiWzZdOyBiMyA9IGJbN107XG4gICAgb3V0WzRdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs1XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbNl0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzddID0gYjAqYTAzICsgYjEqYTEzICsgYjIqYTIzICsgYjMqYTMzO1xuXG4gICAgYjAgPSBiWzhdOyBiMSA9IGJbOV07IGIyID0gYlsxMF07IGIzID0gYlsxMV07XG4gICAgb3V0WzhdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs5XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTBdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxMV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbMTJdOyBiMSA9IGJbMTNdOyBiMiA9IGJbMTRdOyBiMyA9IGJbMTVdO1xuICAgIG91dFsxMl0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzEzXSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTRdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxNV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDQubXVsID0gbWF0NC5tdWx0aXBseTtcblxuLyoqXG4gKiBUcmFuc2xhdGUgYSBtYXQ0IGJ5IHRoZSBnaXZlbiB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdmVjdG9yIHRvIHRyYW5zbGF0ZSBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHYpIHtcbiAgICB2YXIgeCA9IHZbMF0sIHkgPSB2WzFdLCB6ID0gdlsyXSxcbiAgICAgICAgYTAwLCBhMDEsIGEwMiwgYTAzLFxuICAgICAgICBhMTAsIGExMSwgYTEyLCBhMTMsXG4gICAgICAgIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICAgIGlmIChhID09PSBvdXQpIHtcbiAgICAgICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzJdICogeCArIGFbNl0gKiB5ICsgYVsxMF0gKiB6ICsgYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICAgICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICAgICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFswXSA9IGEwMDsgb3V0WzFdID0gYTAxOyBvdXRbMl0gPSBhMDI7IG91dFszXSA9IGEwMztcbiAgICAgICAgb3V0WzRdID0gYTEwOyBvdXRbNV0gPSBhMTE7IG91dFs2XSA9IGExMjsgb3V0WzddID0gYTEzO1xuICAgICAgICBvdXRbOF0gPSBhMjA7IG91dFs5XSA9IGEyMTsgb3V0WzEwXSA9IGEyMjsgb3V0WzExXSA9IGEyMztcblxuICAgICAgICBvdXRbMTJdID0gYTAwICogeCArIGExMCAqIHkgKyBhMjAgKiB6ICsgYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhMDEgKiB4ICsgYTExICogeSArIGEyMSAqIHogKyBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYTAzICogeCArIGExMyAqIHkgKyBhMjMgKiB6ICsgYVsxNV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQ0IGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdGhlIHZlYzMgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICoqL1xubWF0NC5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV0sIHogPSB2WzJdO1xuXG4gICAgb3V0WzBdID0gYVswXSAqIHg7XG4gICAgb3V0WzFdID0gYVsxXSAqIHg7XG4gICAgb3V0WzJdID0gYVsyXSAqIHg7XG4gICAgb3V0WzNdID0gYVszXSAqIHg7XG4gICAgb3V0WzRdID0gYVs0XSAqIHk7XG4gICAgb3V0WzVdID0gYVs1XSAqIHk7XG4gICAgb3V0WzZdID0gYVs2XSAqIHk7XG4gICAgb3V0WzddID0gYVs3XSAqIHk7XG4gICAgb3V0WzhdID0gYVs4XSAqIHo7XG4gICAgb3V0WzldID0gYVs5XSAqIHo7XG4gICAgb3V0WzEwXSA9IGFbMTBdICogejtcbiAgICBvdXRbMTFdID0gYVsxMV0gKiB6O1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0NCBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGUgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQsIGF4aXMpIHtcbiAgICB2YXIgeCA9IGF4aXNbMF0sIHkgPSBheGlzWzFdLCB6ID0gYXhpc1syXSxcbiAgICAgICAgbGVuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiksXG4gICAgICAgIHMsIGMsIHQsXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjMsXG4gICAgICAgIGIwMCwgYjAxLCBiMDIsXG4gICAgICAgIGIxMCwgYjExLCBiMTIsXG4gICAgICAgIGIyMCwgYjIxLCBiMjI7XG5cbiAgICBpZiAoTWF0aC5hYnMobGVuKSA8IEdMTUFUX0VQU0lMT04pIHsgcmV0dXJuIG51bGw7IH1cbiAgICBcbiAgICBsZW4gPSAxIC8gbGVuO1xuICAgIHggKj0gbGVuO1xuICAgIHkgKj0gbGVuO1xuICAgIHogKj0gbGVuO1xuXG4gICAgcyA9IE1hdGguc2luKHJhZCk7XG4gICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgdCA9IDEgLSBjO1xuXG4gICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICBhMTAgPSBhWzRdOyBhMTEgPSBhWzVdOyBhMTIgPSBhWzZdOyBhMTMgPSBhWzddO1xuICAgIGEyMCA9IGFbOF07IGEyMSA9IGFbOV07IGEyMiA9IGFbMTBdOyBhMjMgPSBhWzExXTtcblxuICAgIC8vIENvbnN0cnVjdCB0aGUgZWxlbWVudHMgb2YgdGhlIHJvdGF0aW9uIG1hdHJpeFxuICAgIGIwMCA9IHggKiB4ICogdCArIGM7IGIwMSA9IHkgKiB4ICogdCArIHogKiBzOyBiMDIgPSB6ICogeCAqIHQgLSB5ICogcztcbiAgICBiMTAgPSB4ICogeSAqIHQgLSB6ICogczsgYjExID0geSAqIHkgKiB0ICsgYzsgYjEyID0geiAqIHkgKiB0ICsgeCAqIHM7XG4gICAgYjIwID0geCAqIHogKiB0ICsgeSAqIHM7IGIyMSA9IHkgKiB6ICogdCAtIHggKiBzOyBiMjIgPSB6ICogeiAqIHQgKyBjO1xuXG4gICAgLy8gUGVyZm9ybSByb3RhdGlvbi1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBiMDAgKyBhMTAgKiBiMDEgKyBhMjAgKiBiMDI7XG4gICAgb3V0WzFdID0gYTAxICogYjAwICsgYTExICogYjAxICsgYTIxICogYjAyO1xuICAgIG91dFsyXSA9IGEwMiAqIGIwMCArIGExMiAqIGIwMSArIGEyMiAqIGIwMjtcbiAgICBvdXRbM10gPSBhMDMgKiBiMDAgKyBhMTMgKiBiMDEgKyBhMjMgKiBiMDI7XG4gICAgb3V0WzRdID0gYTAwICogYjEwICsgYTEwICogYjExICsgYTIwICogYjEyO1xuICAgIG91dFs1XSA9IGEwMSAqIGIxMCArIGExMSAqIGIxMSArIGEyMSAqIGIxMjtcbiAgICBvdXRbNl0gPSBhMDIgKiBiMTAgKyBhMTIgKiBiMTEgKyBhMjIgKiBiMTI7XG4gICAgb3V0WzddID0gYTAzICogYjEwICsgYTEzICogYjExICsgYTIzICogYjEyO1xuICAgIG91dFs4XSA9IGEwMCAqIGIyMCArIGExMCAqIGIyMSArIGEyMCAqIGIyMjtcbiAgICBvdXRbOV0gPSBhMDEgKiBiMjAgKyBhMTEgKiBiMjEgKyBhMjEgKiBiMjI7XG4gICAgb3V0WzEwXSA9IGEwMiAqIGIyMCArIGExMiAqIGIyMSArIGEyMiAqIGIyMjtcbiAgICBvdXRbMTFdID0gYTAzICogYjIwICsgYTEzICogYjIxICsgYTIzICogYjIyO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGVYID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSxcbiAgICAgICAgYTIxID0gYVs5XSxcbiAgICAgICAgYTIyID0gYVsxMF0sXG4gICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgICAgIG91dFswXSAgPSBhWzBdO1xuICAgICAgICBvdXRbMV0gID0gYVsxXTtcbiAgICAgICAgb3V0WzJdICA9IGFbMl07XG4gICAgICAgIG91dFszXSAgPSBhWzNdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFs0XSA9IGExMCAqIGMgKyBhMjAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgKyBhMjIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgKyBhMjMgKiBzO1xuICAgIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICAgIG91dFs5XSA9IGEyMSAqIGMgLSBhMTEgKiBzO1xuICAgIG91dFsxMF0gPSBhMjIgKiBjIC0gYTEyICogcztcbiAgICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMjAgPSBhWzhdLFxuICAgICAgICBhMjEgPSBhWzldLFxuICAgICAgICBhMjIgPSBhWzEwXSxcbiAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIHJvd3NcbiAgICAgICAgb3V0WzRdICA9IGFbNF07XG4gICAgICAgIG91dFs1XSAgPSBhWzVdO1xuICAgICAgICBvdXRbNl0gID0gYVs2XTtcbiAgICAgICAgb3V0WzddICA9IGFbN107XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyAtIGEyMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyAtIGEyMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyAtIGEyMyAqIHM7XG4gICAgb3V0WzhdID0gYTAwICogcyArIGEyMCAqIGM7XG4gICAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gICAgb3V0WzEwXSA9IGEwMiAqIHMgKyBhMjIgKiBjO1xuICAgIG91dFsxMV0gPSBhMDMgKiBzICsgYTIzICogYztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQucm90YXRlWiA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGEwMCA9IGFbMF0sXG4gICAgICAgIGEwMSA9IGFbMV0sXG4gICAgICAgIGEwMiA9IGFbMl0sXG4gICAgICAgIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sXG4gICAgICAgIGExMSA9IGFbNV0sXG4gICAgICAgIGExMiA9IGFbNl0sXG4gICAgICAgIGExMyA9IGFbN107XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgICAgIG91dFs4XSAgPSBhWzhdO1xuICAgICAgICBvdXRbOV0gID0gYVs5XTtcbiAgICAgICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgICAgICBvdXRbMTFdID0gYVsxMV07XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyArIGExMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyArIGExMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyArIGExMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyArIGExMyAqIHM7XG4gICAgb3V0WzRdID0gYTEwICogYyAtIGEwMCAqIHM7XG4gICAgb3V0WzVdID0gYTExICogYyAtIGEwMSAqIHM7XG4gICAgb3V0WzZdID0gYTEyICogYyAtIGEwMiAqIHM7XG4gICAgb3V0WzddID0gYTEzICogYyAtIGEwMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiBhbmQgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIHZhciBxdWF0TWF0ID0gbWF0NC5jcmVhdGUoKTtcbiAqICAgICBxdWF0NC50b01hdDQocXVhdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5tdWx0aXBseShkZXN0LCBxdWF0TWF0KTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7dmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5mcm9tUm90YXRpb25UcmFuc2xhdGlvbiA9IGZ1bmN0aW9uIChvdXQsIHEsIHYpIHtcbiAgICAvLyBRdWF0ZXJuaW9uIG1hdGhcbiAgICB2YXIgeCA9IHFbMF0sIHkgPSBxWzFdLCB6ID0gcVsyXSwgdyA9IHFbM10sXG4gICAgICAgIHgyID0geCArIHgsXG4gICAgICAgIHkyID0geSArIHksXG4gICAgICAgIHoyID0geiArIHosXG5cbiAgICAgICAgeHggPSB4ICogeDIsXG4gICAgICAgIHh5ID0geCAqIHkyLFxuICAgICAgICB4eiA9IHggKiB6MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHl6ID0geSAqIHoyLFxuICAgICAgICB6eiA9IHogKiB6MixcbiAgICAgICAgd3ggPSB3ICogeDIsXG4gICAgICAgIHd5ID0gdyAqIHkyLFxuICAgICAgICB3eiA9IHcgKiB6MjtcblxuICAgIG91dFswXSA9IDEgLSAoeXkgKyB6eik7XG4gICAgb3V0WzFdID0geHkgKyB3ejtcbiAgICBvdXRbMl0gPSB4eiAtIHd5O1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0geHkgLSB3ejtcbiAgICBvdXRbNV0gPSAxIC0gKHh4ICsgenopO1xuICAgIG91dFs2XSA9IHl6ICsgd3g7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSB4eiArIHd5O1xuICAgIG91dFs5XSA9IHl6IC0gd3g7XG4gICAgb3V0WzEwXSA9IDEgLSAoeHggKyB5eSk7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IHZbMF07XG4gICAgb3V0WzEzXSA9IHZbMV07XG4gICAgb3V0WzE0XSA9IHZbMl07XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbm1hdDQuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFsyXSA9IHp4IC0gd3k7XG4gICAgb3V0WzNdID0gMDtcblxuICAgIG91dFs0XSA9IHl4IC0gd3o7XG4gICAgb3V0WzVdID0gMSAtIHh4IC0geno7XG4gICAgb3V0WzZdID0genkgKyB3eDtcbiAgICBvdXRbN10gPSAwO1xuXG4gICAgb3V0WzhdID0genggKyB3eTtcbiAgICBvdXRbOV0gPSB6eSAtIHd4O1xuICAgIG91dFsxMF0gPSAxIC0geHggLSB5eTtcbiAgICBvdXRbMTFdID0gMDtcblxuICAgIG91dFsxMl0gPSAwO1xuICAgIG91dFsxM10gPSAwO1xuICAgIG91dFsxNF0gPSAwO1xuICAgIG91dFsxNV0gPSAxO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgZnJ1c3R1bSBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtOdW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuZnJ1c3R1bSA9IGZ1bmN0aW9uIChvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIHJsID0gMSAvIChyaWdodCAtIGxlZnQpLFxuICAgICAgICB0YiA9IDEgLyAodG9wIC0gYm90dG9tKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IChuZWFyICogMikgKiBybDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IChuZWFyICogMikgKiB0YjtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gKHJpZ2h0ICsgbGVmdCkgKiBybDtcbiAgICBvdXRbOV0gPSAodG9wICsgYm90dG9tKSAqIHRiO1xuICAgIG91dFsxMF0gPSAoZmFyICsgbmVhcikgKiBuZjtcbiAgICBvdXRbMTFdID0gLTE7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IChmYXIgKiBuZWFyICogMikgKiBuZjtcbiAgICBvdXRbMTVdID0gMDtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge251bWJlcn0gZm92eSBWZXJ0aWNhbCBmaWVsZCBvZiB2aWV3IGluIHJhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhc3BlY3QgQXNwZWN0IHJhdGlvLiB0eXBpY2FsbHkgdmlld3BvcnQgd2lkdGgvaGVpZ2h0XG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnBlcnNwZWN0aXZlID0gZnVuY3Rpb24gKG91dCwgZm92eSwgYXNwZWN0LCBuZWFyLCBmYXIpIHtcbiAgICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IGYgLyBhc3BlY3Q7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSBmO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxMV0gPSAtMTtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gKDIgKiBmYXIgKiBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQub3J0aG8gPSBmdW5jdGlvbiAob3V0LCBsZWZ0LCByaWdodCwgYm90dG9tLCB0b3AsIG5lYXIsIGZhcikge1xuICAgIHZhciBsciA9IDEgLyAobGVmdCAtIHJpZ2h0KSxcbiAgICAgICAgYnQgPSAxIC8gKGJvdHRvbSAtIHRvcCksXG4gICAgICAgIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgICBvdXRbMF0gPSAtMiAqIGxyO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IDA7XG4gICAgb3V0WzVdID0gLTIgKiBidDtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gMDtcbiAgICBvdXRbOV0gPSAwO1xuICAgIG91dFsxMF0gPSAyICogbmY7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IChsZWZ0ICsgcmlnaHQpICogbHI7XG4gICAgb3V0WzEzXSA9ICh0b3AgKyBib3R0b20pICogYnQ7XG4gICAgb3V0WzE0XSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHt2ZWMzfSBleWUgUG9zaXRpb24gb2YgdGhlIHZpZXdlclxuICogQHBhcmFtIHt2ZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge3ZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5sb29rQXQgPSBmdW5jdGlvbiAob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgICB2YXIgeDAsIHgxLCB4MiwgeTAsIHkxLCB5MiwgejAsIHoxLCB6MiwgbGVuLFxuICAgICAgICBleWV4ID0gZXllWzBdLFxuICAgICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgICBleWV6ID0gZXllWzJdLFxuICAgICAgICB1cHggPSB1cFswXSxcbiAgICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICAgIHVweiA9IHVwWzJdLFxuICAgICAgICBjZW50ZXJ4ID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJ5ID0gY2VudGVyWzFdLFxuICAgICAgICBjZW50ZXJ6ID0gY2VudGVyWzJdO1xuXG4gICAgaWYgKE1hdGguYWJzKGV5ZXggLSBjZW50ZXJ4KSA8IEdMTUFUX0VQU0lMT04gJiZcbiAgICAgICAgTWF0aC5hYnMoZXlleSAtIGNlbnRlcnkpIDwgR0xNQVRfRVBTSUxPTiAmJlxuICAgICAgICBNYXRoLmFicyhleWV6IC0gY2VudGVyeikgPCBHTE1BVF9FUFNJTE9OKSB7XG4gICAgICAgIHJldHVybiBtYXQ0LmlkZW50aXR5KG91dCk7XG4gICAgfVxuXG4gICAgejAgPSBleWV4IC0gY2VudGVyeDtcbiAgICB6MSA9IGV5ZXkgLSBjZW50ZXJ5O1xuICAgIHoyID0gZXlleiAtIGNlbnRlcno7XG5cbiAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KHowICogejAgKyB6MSAqIHoxICsgejIgKiB6Mik7XG4gICAgejAgKj0gbGVuO1xuICAgIHoxICo9IGxlbjtcbiAgICB6MiAqPSBsZW47XG5cbiAgICB4MCA9IHVweSAqIHoyIC0gdXB6ICogejE7XG4gICAgeDEgPSB1cHogKiB6MCAtIHVweCAqIHoyO1xuICAgIHgyID0gdXB4ICogejEgLSB1cHkgKiB6MDtcbiAgICBsZW4gPSBNYXRoLnNxcnQoeDAgKiB4MCArIHgxICogeDEgKyB4MiAqIHgyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB4MCA9IDA7XG4gICAgICAgIHgxID0gMDtcbiAgICAgICAgeDIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHgwICo9IGxlbjtcbiAgICAgICAgeDEgKj0gbGVuO1xuICAgICAgICB4MiAqPSBsZW47XG4gICAgfVxuXG4gICAgeTAgPSB6MSAqIHgyIC0gejIgKiB4MTtcbiAgICB5MSA9IHoyICogeDAgLSB6MCAqIHgyO1xuICAgIHkyID0gejAgKiB4MSAtIHoxICogeDA7XG5cbiAgICBsZW4gPSBNYXRoLnNxcnQoeTAgKiB5MCArIHkxICogeTEgKyB5MiAqIHkyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB5MCA9IDA7XG4gICAgICAgIHkxID0gMDtcbiAgICAgICAgeTIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHkwICo9IGxlbjtcbiAgICAgICAgeTEgKj0gbGVuO1xuICAgICAgICB5MiAqPSBsZW47XG4gICAgfVxuXG4gICAgb3V0WzBdID0geDA7XG4gICAgb3V0WzFdID0geTA7XG4gICAgb3V0WzJdID0gejA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSB4MTtcbiAgICBvdXRbNV0gPSB5MTtcbiAgICBvdXRbNl0gPSB6MTtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IHgyO1xuICAgIG91dFs5XSA9IHkyO1xuICAgIG91dFsxMF0gPSB6MjtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gLSh4MCAqIGV5ZXggKyB4MSAqIGV5ZXkgKyB4MiAqIGV5ZXopO1xuICAgIG91dFsxM10gPSAtKHkwICogZXlleCArIHkxICogZXlleSArIHkyICogZXlleik7XG4gICAgb3V0WzE0XSA9IC0oejAgKiBleWV4ICsgejEgKiBleWV5ICsgejIgKiBleWV6KTtcbiAgICBvdXRbMTVdID0gMTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0NC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0NCgnICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgYVs2XSArICcsICcgKyBhWzddICsgJywgJyArXG4gICAgICAgICAgICAgICAgICAgIGFbOF0gKyAnLCAnICsgYVs5XSArICcsICcgKyBhWzEwXSArICcsICcgKyBhWzExXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVsxMl0gKyAnLCAnICsgYVsxM10gKyAnLCAnICsgYVsxNF0gKyAnLCAnICsgYVsxNV0gKyAnKSc7XG59O1xuXG4vKipcbiAqIFJldHVybnMgRnJvYmVuaXVzIG5vcm0gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gY2FsY3VsYXRlIEZyb2Jlbml1cyBub3JtIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBGcm9iZW5pdXMgbm9ybVxuICovXG5tYXQ0LmZyb2IgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgTWF0aC5wb3coYVs2XSwgMikgKyBNYXRoLnBvdyhhWzZdLCAyKSArIE1hdGgucG93KGFbN10sIDIpICsgTWF0aC5wb3coYVs4XSwgMikgKyBNYXRoLnBvdyhhWzldLCAyKSArIE1hdGgucG93KGFbMTBdLCAyKSArIE1hdGgucG93KGFbMTFdLCAyKSArIE1hdGgucG93KGFbMTJdLCAyKSArIE1hdGgucG93KGFbMTNdLCAyKSArIE1hdGgucG93KGFbMTRdLCAyKSArIE1hdGgucG93KGFbMTVdLCAyKSApKVxufTtcblxuXG5pZih0eXBlb2YoZXhwb3J0cykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZXhwb3J0cy5tYXQ0ID0gbWF0NDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIFF1YXRlcm5pb25cbiAqIEBuYW1lIHF1YXRcbiAqL1xuXG52YXIgcXVhdCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgcXVhdFxuICpcbiAqIEByZXR1cm5zIHtxdWF0fSBhIG5ldyBxdWF0ZXJuaW9uXG4gKi9cbnF1YXQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2V0cyBhIHF1YXRlcm5pb24gdG8gcmVwcmVzZW50IHRoZSBzaG9ydGVzdCByb3RhdGlvbiBmcm9tIG9uZVxuICogdmVjdG9yIHRvIGFub3RoZXIuXG4gKlxuICogQm90aCB2ZWN0b3JzIGFyZSBhc3N1bWVkIHRvIGJlIHVuaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgaW5pdGlhbCB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgZGVzdGluYXRpb24gdmVjdG9yXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQucm90YXRpb25UbyA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdG1wdmVjMyA9IHZlYzMuY3JlYXRlKCk7XG4gICAgdmFyIHhVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygxLDAsMCk7XG4gICAgdmFyIHlVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygwLDEsMCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgICAgIHZhciBkb3QgPSB2ZWMzLmRvdChhLCBiKTtcbiAgICAgICAgaWYgKGRvdCA8IC0wLjk5OTk5OSkge1xuICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB4VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgaWYgKHZlYzMubGVuZ3RoKHRtcHZlYzMpIDwgMC4wMDAwMDEpXG4gICAgICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB5VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgdmVjMy5ub3JtYWxpemUodG1wdmVjMywgdG1wdmVjMyk7XG4gICAgICAgICAgICBxdWF0LnNldEF4aXNBbmdsZShvdXQsIHRtcHZlYzMsIE1hdGguUEkpO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSBlbHNlIGlmIChkb3QgPiAwLjk5OTk5OSkge1xuICAgICAgICAgICAgb3V0WzBdID0gMDtcbiAgICAgICAgICAgIG91dFsxXSA9IDA7XG4gICAgICAgICAgICBvdXRbMl0gPSAwO1xuICAgICAgICAgICAgb3V0WzNdID0gMTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2ZWMzLmNyb3NzKHRtcHZlYzMsIGEsIGIpO1xuICAgICAgICAgICAgb3V0WzBdID0gdG1wdmVjM1swXTtcbiAgICAgICAgICAgIG91dFsxXSA9IHRtcHZlYzNbMV07XG4gICAgICAgICAgICBvdXRbMl0gPSB0bXB2ZWMzWzJdO1xuICAgICAgICAgICAgb3V0WzNdID0gMSArIGRvdDtcbiAgICAgICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBzcGVjaWZpZWQgcXVhdGVybmlvbiB3aXRoIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlblxuICogYXhlcy4gRWFjaCBheGlzIGlzIGEgdmVjMyBhbmQgaXMgZXhwZWN0ZWQgdG8gYmUgdW5pdCBsZW5ndGggYW5kXG4gKiBwZXJwZW5kaWN1bGFyIHRvIGFsbCBvdGhlciBzcGVjaWZpZWQgYXhlcy5cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZpZXcgIHRoZSB2ZWN0b3IgcmVwcmVzZW50aW5nIHRoZSB2aWV3aW5nIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSByaWdodCB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJyaWdodFwiIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSB1cCAgICB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJ1cFwiIGRpcmVjdGlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnNldEF4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hdHIgPSBtYXQzLmNyZWF0ZSgpO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgdmlldywgcmlnaHQsIHVwKSB7XG4gICAgICAgIG1hdHJbMF0gPSByaWdodFswXTtcbiAgICAgICAgbWF0clszXSA9IHJpZ2h0WzFdO1xuICAgICAgICBtYXRyWzZdID0gcmlnaHRbMl07XG5cbiAgICAgICAgbWF0clsxXSA9IHVwWzBdO1xuICAgICAgICBtYXRyWzRdID0gdXBbMV07XG4gICAgICAgIG1hdHJbN10gPSB1cFsyXTtcblxuICAgICAgICBtYXRyWzJdID0gLXZpZXdbMF07XG4gICAgICAgIG1hdHJbNV0gPSAtdmlld1sxXTtcbiAgICAgICAgbWF0cls4XSA9IC12aWV3WzJdO1xuXG4gICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIHF1YXQuZnJvbU1hdDMob3V0LCBtYXRyKSk7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBxdWF0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7cXVhdH0gYSBuZXcgcXVhdGVybmlvblxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY2xvbmUgPSB2ZWM0LmNsb25lO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3F1YXR9IGEgbmV3IHF1YXRlcm5pb25cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmZyb21WYWx1ZXMgPSB2ZWM0LmZyb21WYWx1ZXM7XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHF1YXQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBzb3VyY2UgcXVhdGVybmlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY29weSA9IHZlYzQuY29weTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSBxdWF0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB3IFcgY29tcG9uZW50XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zZXQgPSB2ZWM0LnNldDtcblxuLyoqXG4gKiBTZXQgYSBxdWF0IHRvIHRoZSBpZGVudGl0eSBxdWF0ZXJuaW9uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaWRlbnRpdHkgPSBmdW5jdGlvbihvdXQpIHtcbiAgICBvdXRbMF0gPSAwO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldHMgYSBxdWF0IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFuZCByb3RhdGlvbiBheGlzLFxuICogdGhlbiByZXR1cm5zIGl0LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIGFyb3VuZCB3aGljaCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqKi9cbnF1YXQuc2V0QXhpc0FuZ2xlID0gZnVuY3Rpb24ob3V0LCBheGlzLCByYWQpIHtcbiAgICByYWQgPSByYWQgKiAwLjU7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICAgIG91dFswXSA9IHMgKiBheGlzWzBdO1xuICAgIG91dFsxXSA9IHMgKiBheGlzWzFdO1xuICAgIG91dFsyXSA9IHMgKiBheGlzWzJdO1xuICAgIG91dFszXSA9IE1hdGguY29zKHJhZCk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmFkZCA9IHZlYzQuYWRkO1xuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICB2YXIgYXggPSBhWzBdLCBheSA9IGFbMV0sIGF6ID0gYVsyXSwgYXcgPSBhWzNdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdLCBidyA9IGJbM107XG5cbiAgICBvdXRbMF0gPSBheCAqIGJ3ICsgYXcgKiBieCArIGF5ICogYnogLSBheiAqIGJ5O1xuICAgIG91dFsxXSA9IGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieDtcbiAgICBvdXRbM10gPSBhdyAqIGJ3IC0gYXggKiBieCAtIGF5ICogYnkgLSBheiAqIGJ6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5tdWx0aXBseX1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0Lm11bCA9IHF1YXQubXVsdGlwbHk7XG5cbi8qKlxuICogU2NhbGVzIGEgcXVhdCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zY2FsZSA9IHZlYzQuc2NhbGU7XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVggPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ4ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYng7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF6ICogYng7XG4gICAgb3V0WzJdID0gYXogKiBidyAtIGF5ICogYng7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ5ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF3ICogYnk7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF4ICogYnk7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF5ICogYnk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBaIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVogPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ6ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF5ICogYno7XG4gICAgb3V0WzFdID0gYXkgKiBidyAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYno7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF6ICogYno7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgVyBjb21wb25lbnQgb2YgYSBxdWF0IGZyb20gdGhlIFgsIFksIGFuZCBaIGNvbXBvbmVudHMuXG4gKiBBc3N1bWVzIHRoYXQgcXVhdGVybmlvbiBpcyAxIHVuaXQgaW4gbGVuZ3RoLlxuICogQW55IGV4aXN0aW5nIFcgY29tcG9uZW50IHdpbGwgYmUgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBXIGNvbXBvbmVudCBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LmNhbGN1bGF0ZVcgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG5cbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSAtTWF0aC5zcXJ0KE1hdGguYWJzKDEuMCAtIHggKiB4IC0geSAqIHkgLSB6ICogeikpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byBxdWF0J3NcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmRvdCA9IHZlYzQuZG90O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlcnAgPSB2ZWM0LmxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuc2xlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgLy8gYmVuY2htYXJrczpcbiAgICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIGF4ID0gYVswXSwgYXkgPSBhWzFdLCBheiA9IGFbMl0sIGF3ID0gYVszXSxcbiAgICAgICAgYnggPSBiWzBdLCBieSA9IGJbMV0sIGJ6ID0gYlsyXSwgYncgPSBiWzNdO1xuXG4gICAgdmFyICAgICAgICBvbWVnYSwgY29zb20sIHNpbm9tLCBzY2FsZTAsIHNjYWxlMTtcblxuICAgIC8vIGNhbGMgY29zaW5lXG4gICAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3O1xuICAgIC8vIGFkanVzdCBzaWducyAoaWYgbmVjZXNzYXJ5KVxuICAgIGlmICggY29zb20gPCAwLjAgKSB7XG4gICAgICAgIGNvc29tID0gLWNvc29tO1xuICAgICAgICBieCA9IC0gYng7XG4gICAgICAgIGJ5ID0gLSBieTtcbiAgICAgICAgYnogPSAtIGJ6O1xuICAgICAgICBidyA9IC0gYnc7XG4gICAgfVxuICAgIC8vIGNhbGN1bGF0ZSBjb2VmZmljaWVudHNcbiAgICBpZiAoICgxLjAgLSBjb3NvbSkgPiAwLjAwMDAwMSApIHtcbiAgICAgICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgICAgIG9tZWdhICA9IE1hdGguYWNvcyhjb3NvbSk7XG4gICAgICAgIHNpbm9tICA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgc2NhbGUwID0gTWF0aC5zaW4oKDEuMCAtIHQpICogb21lZ2EpIC8gc2lub207XG4gICAgICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbTtcbiAgICB9IGVsc2UgeyAgICAgICAgXG4gICAgICAgIC8vIFwiZnJvbVwiIGFuZCBcInRvXCIgcXVhdGVybmlvbnMgYXJlIHZlcnkgY2xvc2UgXG4gICAgICAgIC8vICAuLi4gc28gd2UgY2FuIGRvIGEgbGluZWFyIGludGVycG9sYXRpb25cbiAgICAgICAgc2NhbGUwID0gMS4wIC0gdDtcbiAgICAgICAgc2NhbGUxID0gdDtcbiAgICB9XG4gICAgLy8gY2FsY3VsYXRlIGZpbmFsIHZhbHVlc1xuICAgIG91dFswXSA9IHNjYWxlMCAqIGF4ICsgc2NhbGUxICogYng7XG4gICAgb3V0WzFdID0gc2NhbGUwICogYXkgKyBzY2FsZTEgKiBieTtcbiAgICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6O1xuICAgIG91dFszXSA9IHNjYWxlMCAqIGF3ICsgc2NhbGUxICogYnc7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgaW52ZXJzZSBvZiBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBpbnZlcnNlIG9mXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgZG90ID0gYTAqYTAgKyBhMSphMSArIGEyKmEyICsgYTMqYTMsXG4gICAgICAgIGludkRvdCA9IGRvdCA/IDEuMC9kb3QgOiAwO1xuICAgIFxuICAgIC8vIFRPRE86IFdvdWxkIGJlIGZhc3RlciB0byByZXR1cm4gWzAsMCwwLDBdIGltbWVkaWF0ZWx5IGlmIGRvdCA9PSAwXG5cbiAgICBvdXRbMF0gPSAtYTAqaW52RG90O1xuICAgIG91dFsxXSA9IC1hMSppbnZEb3Q7XG4gICAgb3V0WzJdID0gLWEyKmludkRvdDtcbiAgICBvdXRbM10gPSBhMyppbnZEb3Q7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY29uanVnYXRlIG9mIGEgcXVhdFxuICogSWYgdGhlIHF1YXRlcm5pb24gaXMgbm9ybWFsaXplZCwgdGhpcyBmdW5jdGlvbiBpcyBmYXN0ZXIgdGhhbiBxdWF0LmludmVyc2UgYW5kIHByb2R1Y2VzIHRoZSBzYW1lIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBjb25qdWdhdGUgb2ZcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xucXVhdC5jb25qdWdhdGUgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF07XG4gICAgb3V0WzFdID0gLWFbMV07XG4gICAgb3V0WzJdID0gLWFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubGVuZ3RoID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBxdWF0Lmxlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlbiA9IHF1YXQubGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zcXVhcmVkTGVuZ3RoID0gdmVjNC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5zcXVhcmVkTGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuc3FyTGVuID0gcXVhdC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubm9ybWFsaXplID0gdmVjNC5ub3JtYWxpemU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHF1YXRlcm5pb24gZnJvbSB0aGUgZ2l2ZW4gM3gzIHJvdGF0aW9uIG1hdHJpeC5cbiAqXG4gKiBOT1RFOiBUaGUgcmVzdWx0YW50IHF1YXRlcm5pb24gaXMgbm90IG5vcm1hbGl6ZWQsIHNvIHlvdSBzaG91bGQgYmUgc3VyZVxuICogdG8gcmVub3JtYWxpemUgdGhlIHF1YXRlcm5pb24geW91cnNlbGYgd2hlcmUgbmVjZXNzYXJ5LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHttYXQzfSBtIHJvdGF0aW9uIG1hdHJpeFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuZnJvbU1hdDMgPSBmdW5jdGlvbihvdXQsIG0pIHtcbiAgICAvLyBBbGdvcml0aG0gaW4gS2VuIFNob2VtYWtlJ3MgYXJ0aWNsZSBpbiAxOTg3IFNJR0dSQVBIIGNvdXJzZSBub3Rlc1xuICAgIC8vIGFydGljbGUgXCJRdWF0ZXJuaW9uIENhbGN1bHVzIGFuZCBGYXN0IEFuaW1hdGlvblwiLlxuICAgIHZhciBmVHJhY2UgPSBtWzBdICsgbVs0XSArIG1bOF07XG4gICAgdmFyIGZSb290O1xuXG4gICAgaWYgKCBmVHJhY2UgPiAwLjAgKSB7XG4gICAgICAgIC8vIHx3fCA+IDEvMiwgbWF5IGFzIHdlbGwgY2hvb3NlIHcgPiAxLzJcbiAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMS4wKTsgIC8vIDJ3XG4gICAgICAgIG91dFszXSA9IDAuNSAqIGZSb290O1xuICAgICAgICBmUm9vdCA9IDAuNS9mUm9vdDsgIC8vIDEvKDR3KVxuICAgICAgICBvdXRbMF0gPSAobVs3XS1tWzVdKSpmUm9vdDtcbiAgICAgICAgb3V0WzFdID0gKG1bMl0tbVs2XSkqZlJvb3Q7XG4gICAgICAgIG91dFsyXSA9IChtWzNdLW1bMV0pKmZSb290O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHx3fCA8PSAxLzJcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBpZiAoIG1bNF0gPiBtWzBdIClcbiAgICAgICAgICBpID0gMTtcbiAgICAgICAgaWYgKCBtWzhdID4gbVtpKjMraV0gKVxuICAgICAgICAgIGkgPSAyO1xuICAgICAgICB2YXIgaiA9IChpKzEpJTM7XG4gICAgICAgIHZhciBrID0gKGkrMiklMztcbiAgICAgICAgXG4gICAgICAgIGZSb290ID0gTWF0aC5zcXJ0KG1baSozK2ldLW1baiozK2pdLW1bayozK2tdICsgMS4wKTtcbiAgICAgICAgb3V0W2ldID0gMC41ICogZlJvb3Q7XG4gICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7XG4gICAgICAgIG91dFszXSA9IChtW2sqMytqXSAtIG1baiozK2tdKSAqIGZSb290O1xuICAgICAgICBvdXRbal0gPSAobVtqKjMraV0gKyBtW2kqMytqXSkgKiBmUm9vdDtcbiAgICAgICAgb3V0W2tdID0gKG1bayozK2ldICsgbVtpKjMra10pICogZlJvb3Q7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBxdWF0ZW5pb25cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG5xdWF0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdxdWF0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMucXVhdCA9IHF1YXQ7XG59XG47XG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbiAgfSkoc2hpbS5leHBvcnRzKTtcbn0pKHRoaXMpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBjb25zdGFudCh2YWx1ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVOdW1iZXIoYSwgYiwgdCkge1xuICAgIHJldHVybiAoYSAqICgxIC0gdCkpICsgKGIgKiB0KTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVBcnJheShhLCBiLCB0KSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBpbnRlcnBvbGF0ZU51bWJlcihhW2ldLCBiW2ldLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0c1snaW50ZXJwb2xhdGVkJ10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzLFxuICAgICAgICBiYXNlID0gZi5iYXNlIHx8IDEsXG4gICAgICAgIGludGVycG9sYXRlID0gQXJyYXkuaXNBcnJheShzdG9wc1swXVsxXSkgPyBpbnRlcnBvbGF0ZUFycmF5IDogaW50ZXJwb2xhdGVOdW1iZXI7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oeikge1xuICAgICAgICAvLyBmaW5kIHRoZSB0d28gc3RvcHMgd2hpY2ggdGhlIGN1cnJlbnQgeiBpcyBiZXR3ZWVuXG4gICAgICAgIHZhciBsb3csIGhpZ2g7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0b3AgPSBzdG9wc1tpXTtcblxuICAgICAgICAgICAgaWYgKHN0b3BbMF0gPD0geikge1xuICAgICAgICAgICAgICAgIGxvdyA9IHN0b3A7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdG9wWzBdID4geikge1xuICAgICAgICAgICAgICAgIGhpZ2ggPSBzdG9wO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxvdyAmJiBoaWdoKSB7XG4gICAgICAgICAgICB2YXIgem9vbURpZmYgPSBoaWdoWzBdIC0gbG93WzBdLFxuICAgICAgICAgICAgICAgIHpvb21Qcm9ncmVzcyA9IHogLSBsb3dbMF0sXG5cbiAgICAgICAgICAgICAgICB0ID0gYmFzZSA9PT0gMSA/XG4gICAgICAgICAgICAgICAgem9vbVByb2dyZXNzIC8gem9vbURpZmYgOlxuICAgICAgICAgICAgICAgIChNYXRoLnBvdyhiYXNlLCB6b29tUHJvZ3Jlc3MpIC0gMSkgLyAoTWF0aC5wb3coYmFzZSwgem9vbURpZmYpIC0gMSk7XG5cbiAgICAgICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZShsb3dbMV0sIGhpZ2hbMV0sIHQpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobG93KSB7XG4gICAgICAgICAgICByZXR1cm4gbG93WzFdO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoaGlnaCkge1xuICAgICAgICAgICAgcmV0dXJuIGhpZ2hbMV07XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuZXhwb3J0c1sncGllY2V3aXNlLWNvbnN0YW50J10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHopIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHN0b3BzW2ldWzBdID4geikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9wc1tpID09PSAwID8gMCA6IGkgLSAxXVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdG9wc1tzdG9wcy5sZW5ndGggLSAxXVsxXTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi4vLi4vcmVmZXJlbmNlL2xhdGVzdC5qcycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9wYXJzZWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHlsZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZShzdHlsZSwgcmVmZXJlbmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xudmFyIGZvcm1hdCA9IHJlcXVpcmUoJ3V0aWwnKS5mb3JtYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3R5bGUsIHJlZmVyZW5jZSkge1xuXG4gICAgdmFyIGNvbnN0YW50cyA9IHN0eWxlLmNvbnN0YW50cyB8fCB7fSxcbiAgICAgICAgbGF5ZXJzID0ge30sXG4gICAgICAgIGVycm9ycyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZXJyb3Ioa2V5LCB2YWwgLyosIG1lc3NhZ2UsIC4uLiovKSB7XG4gICAgICAgIHZhciBlcnIgPSB7XG4gICAgICAgICAgICBtZXNzYWdlOiAoa2V5ID8ga2V5ICsgJzogJyA6ICcnKSArXG4gICAgICAgICAgICBmb3JtYXQuYXBwbHkoZm9ybWF0LCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsLl9fbGluZV9fKSB7XG4gICAgICAgICAgICBlcnIubGluZSA9IHZhbC5fX2xpbmVfXztcbiAgICAgICAgfVxuXG4gICAgICAgIGVycm9ycy5wdXNoKGVycik7XG4gICAgfVxuXG4gICAgLy8gTWFpbiByZWN1cnNpdmUgdmFsaWRhdGlvbiBmdW5jdGlvbi4gVHJhY2tzOlxuICAgIC8vXG4gICAgLy8gLSBrZXk6IHN0cmluZyByZXByZXNlbnRpbmcgbG9jYXRpb24gb2YgdmFsaWRhdGlvbiBpbiBzdHlsZSB0cmVlLiBVc2VkIG9ubHlcbiAgICAvLyAgIGZvciBtb3JlIGluZm9ybWF0aXZlIGVycm9yIHJlcG9ydGluZy5cbiAgICAvLyAtIHZhbDogY3VycmVudCB2YWx1ZSBmcm9tIHN0eWxlIGJlaW5nIGV2YWx1YXRlZC4gTWF5IGJlIGFueXRoaW5nIGZyb20gYVxuICAgIC8vICAgaGlnaCBsZXZlbCBvYmplY3QgdGhhdCBuZWVkcyB0byBiZSBkZXNjZW5kZWQgaW50byBkZWVwZXIgb3IgYSBzaW1wbGVcbiAgICAvLyAgIHNjYWxhciB2YWx1ZS5cbiAgICAvLyAtIHNwZWM6IGN1cnJlbnQgc3BlYyBiZWluZyBldmFsdWF0ZWQuIFRyYWNrcyB2YWwuXG4gICAgLy9cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcblxuICAgICAgICAvLyBDb25zdGFudHNcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIHZhbFswXSA9PT0gJ0AnKSB7XG4gICAgICAgICAgICBpZiAoISh2YWwgaW4gY29uc3RhbnRzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2NvbnN0YW50IFwiJXNcIiBub3QgZm91bmQnLCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsID0gY29uc3RhbnRzW3ZhbF07XG4gICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRnVuY3Rpb25zXG4gICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uICYmIHR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRhdGUuZnVuY3Rpb24oa2V5LCB2YWwsIHNwZWMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNwZWMudHlwZSkge1xuICAgICAgICAgICAgdmFyIHZhbGlkYXRvciA9IHZhbGlkYXRlW3NwZWMudHlwZV07XG4gICAgICAgICAgICBpZiAodmFsaWRhdG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbGlkYXRvcihrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzcGVjID0gcmVmZXJlbmNlW3NwZWMudHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHNwZWMpO1xuICAgIH1cblxuICAgIHZhbGlkYXRlLmNvbnN0YW50cyA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICBpZiAodHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ29iamVjdCBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGsgaW4gdmFsKSB7XG4gICAgICAgICAgICBpZiAoa1swXSAhPT0gJ0AnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJy4nICsgaywgdmFsW2tdLCAnY29uc3RhbnRzIG11c3Qgc3RhcnQgd2l0aCBcIkBcIicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLnNvdXJjZSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnXCJ0eXBlXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgICAgICBjYXNlICdyYXN0ZXInOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV90aWxlKTtcblxuICAgICAgICAgICAgICAgIGlmICgndXJsJyBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChbJ3R5cGUnLCAndXJsJywgJ3RpbGVTaXplJ10uaW5kZXhPZihwcm9wKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXkgKyAnLicgKyBwcm9wLCB2YWxbcHJvcF0sICdhIHNvdXJjZSB3aXRoIGEgXCJ1cmxcIiBwcm9wZXJ0eSBtYXkgbm90IGluY2x1ZGUgYSBcIiVzXCIgcHJvcGVydHknLCBwcm9wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZ2VvanNvbic6XG4gICAgICAgICAgICAgICAgdmFsaWRhdGUub2JqZWN0KGtleSwgdmFsLCByZWZlcmVuY2Uuc291cmNlX2dlb2pzb24pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndmlkZW8nOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV92aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJy50eXBlJywgdmFsLnR5cGUsIHt2YWx1ZXM6IFsndmVjdG9yJywgJ3Jhc3RlcicsICdnZW9qc29uJywgJ3ZpZGVvJ119KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YWxpZGF0ZS5sYXllciA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUgJiYgIXZhbC5yZWYpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnZWl0aGVyIFwidHlwZVwiIG9yIFwicmVmXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpLFxuICAgICAgICAgICAgcmVmID0gdW5idW5kbGUodmFsLnJlZik7XG5cbiAgICAgICAgaWYgKHZhbC5pZCkge1xuICAgICAgICAgICAgaWYgKGxheWVyc1t2YWwuaWRdKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwuaWQsICdkdXBsaWNhdGUgbGF5ZXIgaWQgXCIlc1wiLCBwcmV2aW91c2x5IHVzZWQgYXQgbGluZSAlZCcsIHZhbC5pZCwgbGF5ZXJzW3ZhbC5pZF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsYXllcnNbdmFsLmlkXSA9IHZhbC5pZC5fX2xpbmVfXztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgncmVmJyBpbiB2YWwpIHtcbiAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJywgJ2ZpbHRlcicsICdsYXlvdXQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHAgaW4gdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsW3BdLCAnXCIlc1wiIGlzIHByb2hpYml0ZWQgZm9yIHJlZiBsYXllcnMnLCBwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHBhcmVudDtcblxuICAgICAgICAgICAgc3R5bGUubGF5ZXJzLmZvckVhY2goZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAobGF5ZXIuaWQgPT0gcmVmKSBwYXJlbnQgPSBsYXllcjtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBsYXllciBcIiVzXCIgbm90IGZvdW5kJywgcmVmKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50LnJlZikge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBjYW5ub3QgcmVmZXJlbmNlIGFub3RoZXIgcmVmIGxheWVyJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJlbnQudHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlICE9PSAnYmFja2dyb3VuZCcpIHtcbiAgICAgICAgICAgIGlmICghdmFsLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcInNvdXJjZVwiJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzb3VyY2UgPSBzdHlsZS5zb3VyY2VzW3ZhbC5zb3VyY2VdO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ3NvdXJjZSBcIiVzXCIgbm90IGZvdW5kJywgdmFsLnNvdXJjZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzb3VyY2UudHlwZSA9PSAndmVjdG9yJyAmJiB0eXBlID09ICdyYXN0ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ2xheWVyIFwiJXNcIiByZXF1aXJlcyBhIHJhc3RlciBzb3VyY2UnLCB2YWwuaWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc291cmNlLnR5cGUgPT0gJ3Jhc3RlcicgJiYgdHlwZSAhPSAncmFzdGVyJykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbC5zb3VyY2UsICdsYXllciBcIiVzXCIgcmVxdWlyZXMgYSB2ZWN0b3Igc291cmNlJywgdmFsLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5sYXllciwge1xuICAgICAgICAgICAgZmlsdGVyOiB2YWxpZGF0ZS5maWx0ZXIsXG4gICAgICAgICAgICBsYXlvdXQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ2xheW91dF8nICsgdHlwZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGUgJiYgc3BlYyAmJiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFpbnQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ3BhaW50XycgKyB0eXBlXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZSAmJiBzcGVjICYmIHZhbGlkYXRlKGtleSwgdmFsLCBzcGVjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLm9iamVjdCA9IGZ1bmN0aW9uIChrZXksIHZhbCwgc3BlYywgdmFsaWRhdG9ycykge1xuICAgICAgICB2YWxpZGF0b3JzID0gdmFsaWRhdG9ycyB8fCB7fTtcblxuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdvYmplY3QgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBrIGluIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNwZWNrZXkgPSBrLnNwbGl0KCcuJylbMF07IC8vIHRyZWF0ICdwYWludC4qJyBhcyAncGFpbnQnXG4gICAgICAgICAgICB2YXIgZGVmID0gc3BlY1tzcGVja2V5XSB8fCBzcGVjWycqJ107XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHNwZWNrZXkubWF0Y2goL14oLiopLXRyYW5zaXRpb24kLyk7XG5cbiAgICAgICAgICAgIGlmIChkZWYpIHtcbiAgICAgICAgICAgICAgICAodmFsaWRhdG9yc1tzcGVja2V5XSB8fCB2YWxpZGF0ZSkoKGtleSA/IGtleSArICcuJyA6IGtleSkgKyBrLCB2YWxba10sIGRlZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zaXRpb24gJiYgc3BlY1t0cmFuc2l0aW9uWzFdXSAmJiBzcGVjW3RyYW5zaXRpb25bMV1dLnRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZSgoa2V5ID8ga2V5ICsgJy4nIDoga2V5KSArIGssIHZhbFtrXSwgcmVmZXJlbmNlLnRyYW5zaXRpb24pO1xuICAgICAgICAgICAgLy8gdG9sZXJhdGUgcm9vdC1sZXZlbCBleHRyYSBrZXlzICYgYXJiaXRyYXJ5IGxheWVyIHByb3BlcnRpZXNcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ICE9PSAnJyAmJiBrZXkuc3BsaXQoJy4nKS5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbFtrXSwgJ3Vua25vd24gcHJvcGVydHkgXCIlc1wiJywgayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBsIGluIHNwZWMpIHtcbiAgICAgICAgICAgIGlmIChzcGVjW2xdLnJlcXVpcmVkICYmIHNwZWNbbF1bJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIHZhbFtsXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwiJXNcIicsIGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmFycmF5ID0gZnVuY3Rpb24gKGtleSwgdmFsLCBzcGVjLCB2YWxpZGF0b3IpIHtcbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzcGVjLmxlbmd0aCAmJiB2YWwubGVuZ3RoICE9PSBzcGVjLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgbGVuZ3RoICVkIGV4cGVjdGVkLCBsZW5ndGggJWQgZm91bmQnLCBzcGVjLmxlbmd0aCwgdmFsLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdmFsdWUgPSB7XG4gICAgICAgICAgICBcInR5cGVcIjogc3BlYy52YWx1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzdHlsZS52ZXJzaW9uIDwgNykge1xuICAgICAgICAgICAgdmFsdWUuZnVuY3Rpb24gPSBzcGVjLmZ1bmN0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZl8oc3BlYy52YWx1ZSkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHNwZWMudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgKHZhbGlkYXRvciB8fCB2YWxpZGF0ZSkoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZmlsdGVyID0gZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICAgICAgdmFyIHR5cGU7XG5cbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwubGVuZ3RoIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnZmlsdGVyIGFycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCAxIGVsZW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1swXScsIHZhbFswXSwgcmVmZXJlbmNlLmZpbHRlcl9vcGVyYXRvcik7XG5cbiAgICAgICAgc3dpdGNoICh1bmJ1bmRsZSh2YWxbMF0pKSB7XG4gICAgICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID49IDIgJiYgdmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdcIiR0eXBlXCIgY2Fubm90IGJlIHVzZSB3aXRoIG9wZXJhdG9yIFwiJXNcIicsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnPT0nOlxuICAgICAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoICE9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdmaWx0ZXIgYXJyYXkgZm9yIG9wZXJhdG9yIFwiJXNcIiBtdXN0IGhhdmUgMyBlbGVtZW50cycsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnaW4nOlxuICAgICAgICAgICAgY2FzZSAnIWluJzpcbiAgICAgICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSB0eXBlb2ZfKHZhbFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ3N0cmluZyBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWxbMV1bMF0gPT09ICdAJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ2ZpbHRlciBrZXkgY2Fubm90IGJlIGEgY29uc3RhbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWxbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCByZWZlcmVuY2UuZ2VvbWV0cnlfdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgdmFsW2ldWzBdID09PSAnQCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbJyArIGkgKyAnXScsIHZhbFtpXSwgJ2ZpbHRlciB2YWx1ZSBjYW5ub3QgYmUgYSBjb25zdGFudCcpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgIT09ICdzdHJpbmcnICYmIHR5cGUgIT09ICdudW1iZXInICYmIHR5cGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCAnc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4gZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2FueSc6XG4gICAgICAgICAgICBjYXNlICdhbGwnOlxuICAgICAgICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZS5maWx0ZXIoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZnVuY3Rpb24gPSBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5mdW5jdGlvbiwge1xuICAgICAgICAgICAgc3RvcHM6IGZ1bmN0aW9uIChrZXksIHZhbCwgYXJyYXlTcGVjKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RTdG9wID0gLUluZmluaXR5O1xuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmFycmF5KGtleSwgdmFsLCBhcnJheVNwZWMsIGZ1bmN0aW9uIHZhbGlkYXRlU3RvcChrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mXyh2YWwpICE9PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdhcnJheSBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlb2ZfKHZhbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2FycmF5IGxlbmd0aCAlZCBleHBlY3RlZCwgbGVuZ3RoICVkIGZvdW5kJywgMiwgdmFsLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZShrZXkgKyAnWzBdJywgdmFsWzBdLCB7dHlwZTogJ251bWJlcid9KTtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGUoa2V5ICsgJ1sxXScsIHZhbFsxXSwgc3BlYyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZl8odmFsWzBdKSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uID09PSAncGllY2V3aXNlLWNvbnN0YW50JyAmJiB2YWxbMF0gJSAxICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1swXScsIHZhbFswXSwgJ3pvb20gbGV2ZWwgZm9yIHBpZWNld2lzZS1jb25zdGFudCBmdW5jdGlvbnMgbXVzdCBiZSBhbiBpbnRlZ2VyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxbMF0gPCBsYXN0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbMF0nLCB2YWxbMF0sICdhcnJheSBzdG9wcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFN0b3AgPSB2YWxbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2ZfKHZhbCkgPT09ICdhcnJheScgJiYgdmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2FycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgc3RvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmVudW0gPSBmdW5jdGlvbiAoa2V5LCB2YWwsIHNwZWMpIHtcbiAgICAgICAgaWYgKHNwZWMudmFsdWVzLmluZGV4T2YodW5idW5kbGUodmFsKSkgPT09IC0xKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2V4cGVjdGVkIG9uZSBvZiBbJXNdLCAlcyBmb3VuZCcsIHNwZWMudmFsdWVzLmpvaW4oJywgJyksIHZhbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuY29sb3IgPSBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2NvbG9yIGV4cGVjdGVkLCAlcyBmb3VuZCcsIHR5cGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcnNlQ1NTQ29sb3IodmFsKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdjb2xvciBleHBlY3RlZCwgXCIlc1wiIGZvdW5kJywgdmFsKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB0eXBlVmFsaWRhdG9yKGV4cGVjdGVkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICAgICAgdmFyIGFjdHVhbCA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgICAgIGlmIChhY3R1YWwgIT09IGV4cGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBleHBlY3RlZCwgJXMgZm91bmQnLCBleHBlY3RlZCwgYWN0dWFsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCdtaW5pbXVtJyBpbiBzcGVjICYmIHZhbCA8IHNwZWMubWluaW11bSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnJXMgaXMgbGVzcyB0aGFuIHRoZSBtaW5pbXVtIHZhbHVlICVzJywgdmFsLCBzcGVjLm1pbmltdW0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJ21heGltdW0nIGluIHNwZWMgJiYgdmFsID4gc3BlYy5tYXhpbXVtKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gdmFsdWUgJXMnLCB2YWwsIHNwZWMubWF4aW11bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFsaWRhdGUubnVtYmVyID0gdHlwZVZhbGlkYXRvcignbnVtYmVyJyk7XG4gICAgdmFsaWRhdGUuc3RyaW5nID0gdHlwZVZhbGlkYXRvcignc3RyaW5nJyk7XG4gICAgdmFsaWRhdGUuYm9vbGVhbiA9IHR5cGVWYWxpZGF0b3IoJ2Jvb2xlYW4nKTtcblxuICAgIHZhbGlkYXRlWycqJ10gPSBmdW5jdGlvbigpIHt9O1xuXG4gICAgdmFsaWRhdGUoJycsIHN0eWxlLCByZWZlcmVuY2UuJHJvb3QpO1xuXG4gICAgcmV0dXJuIGVycm9ycztcbn07XG5cbmZ1bmN0aW9uIHR5cGVvZl8odmFsKSB7XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE51bWJlcilcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBTdHJpbmcpXG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBpZiAodmFsIGluc3RhbmNlb2YgQm9vbGVhbilcbiAgICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICByZXR1cm4gJ2FycmF5JztcbiAgICBpZiAodmFsID09PSBudWxsKVxuICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgIHJldHVybiB0eXBlb2YgdmFsO1xufVxuXG5mdW5jdGlvbiB1bmJ1bmRsZShfKSB7XG4gICAgaWYgKF8gaW5zdGFuY2VvZiBOdW1iZXIgfHxcbiAgICAgICAgXyBpbnN0YW5jZW9mIFN0cmluZyB8fFxuICAgICAgICBfIGluc3RhbmNlb2YgQm9vbGVhbikge1xuICAgICAgICByZXR1cm4gXy52YWx1ZU9mKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIF87XG4gICAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3Y3Lmpzb24nKTtcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkdmVyc2lvblwiOiA3LFxuICBcIiRyb290XCI6IHtcbiAgICBcInZlcnNpb25cIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICA3XG4gICAgICBdLFxuICAgICAgXCJkb2NcIjogXCJTdHlsZXNoZWV0IHZlcnNpb24gbnVtYmVyLiBNdXN0IGJlIDcuXCJcbiAgICB9LFxuICAgIFwibmFtZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBodW1hbi1yZWFkYWJsZSBuYW1lIGZvciB0aGUgc3R5bGUuXCJcbiAgICB9LFxuICAgIFwiY29uc3RhbnRzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbnN0YW50c1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBvYmplY3Qgb2YgY29uc3RhbnRzIHRvIGJlIHJlZmVyZW5jZWQgaW4gbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZXNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwic291cmNlc1wiLFxuICAgICAgXCJkb2NcIjogXCJEYXRhIHNvdXJjZSBzcGVjaWZpY2F0aW9ucy5cIlxuICAgIH0sXG4gICAgXCJzcHJpdGVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgYmFzZSBVUkwgZm9yIHJldHJpZXZpbmcgdGhlIHNwcml0ZSBpbWFnZSBhbmQgbWV0YWRhdGEuIFRoZSBleHRlbnNpb25zIGAucG5nYCwgYC5qc29uYCBhbmQgc2NhbGUgZmFjdG9yIGBAMngucG5nYCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQuXCJcbiAgICB9LFxuICAgIFwiZ2x5cGhzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJBIFVSTCB0ZW1wbGF0ZSBmb3IgbG9hZGluZyBzaWduZWQtZGlzdGFuY2UtZmllbGQgZ2x5cGggc2V0cyBpbiBQQkYgZm9ybWF0LiBWYWxpZCB0b2tlbnMgYXJlIHtmb250c3RhY2t9IGFuZCB7cmFuZ2V9LlwiXG4gICAgfSxcbiAgICBcInRyYW5zaXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwidHJhbnNpdGlvblwiLFxuICAgICAgXCJkb2NcIjogXCJBIGdsb2JhbCB0cmFuc2l0aW9uIGRlZmluaXRpb24gdG8gdXNlIGFzIGEgZGVmYXVsdCBhY3Jvc3MgcHJvcGVydGllcy5cIlxuICAgIH0sXG4gICAgXCJsYXllcnNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJsYXllclwiLFxuICAgICAgXCJkb2NcIjogXCJMYXllcnMgd2lsbCBiZSBkcmF3biBpbiB0aGUgb3JkZXIgb2YgdGhpcyBhcnJheS5cIlxuICAgIH1cbiAgfSxcbiAgXCJjb25zdGFudHNcIjoge1xuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIkEgY29uc3RhbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkIHZlcmJhdGltIGluIHRoZSByZWZlcmVuY2luZyBwbGFjZS4gVGhpcyBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBvYmplY3RzIGFuZCBhcnJheXMuIEFsbCB2YXJpYWJsZSBuYW1lcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggYW4gYEBgIHN5bWJvbC5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VzXCI6IHtcbiAgICBcIipcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic291cmNlXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmljYXRpb24gb2YgYSBkYXRhIHNvdXJjZS4gRm9yIHZlY3RvciBhbmQgcmFzdGVyIHNvdXJjZXMsIGVpdGhlciBUaWxlSlNPTiBvciBhIFVSTCB0byBhIFRpbGVKU09OIG11c3QgYmUgcHJvdmlkZWQuIEZvciBHZW9KU09OIGFuZCB2aWRlbyBzb3VyY2VzLCBhIFVSTCBtdXN0IGJlIHByb3ZpZGVkLlwiXG4gICAgfVxuICB9LFxuICBcInNvdXJjZVwiOiBbXG4gICAgXCJzb3VyY2VfdGlsZVwiLFxuICAgIFwic291cmNlX2dlb2pzb25cIixcbiAgICBcInNvdXJjZV92aWRlb1wiXG4gIF0sXG4gIFwic291cmNlX3RpbGVcIjoge1xuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmVjdG9yXCIsXG4gICAgICAgIFwicmFzdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlRoZSBkYXRhIHR5cGUgb2YgdGhlIHNvdXJjZS5cIlxuICAgIH0sXG4gICAgXCJ1cmxcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgVVJMIHRvIGEgVGlsZUpTT04gcmVzb3VyY2UuIFN1cHBvcnRlZCBwcm90b2NvbHMgYXJlIGBodHRwOmAsIGBodHRwczpgLCBhbmQgYG1hcGJveDovLzxtYXBpZD5gLlwiXG4gICAgfSxcbiAgICBcInRpbGVzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkFuIGFycmF5IG9mIG9uZSBvciBtb3JlIHRpbGUgc291cmNlIFVSTHMsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSB6b29tIGxldmVsIGZvciB3aGljaCB0aWxlcyBhcmUgYXZhaWxhYmxlLCBhcyBpbiB0aGUgVGlsZUpTT04gc3BlYy5cIlxuICAgIH0sXG4gICAgXCJtYXh6b29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJNYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHdoaWNoIHRpbGVzIGFyZSBhdmFpbGFibGUsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLiBEYXRhIGZyb20gdGlsZXMgYXQgdGhlIG1heHpvb20gYXJlIHVzZWQgd2hlbiBkaXNwbGF5aW5nIHRoZSBtYXAgYXQgaGlnaGVyIHpvb20gbGV2ZWxzLlwiXG4gICAgfSxcbiAgICBcInRpbGVTaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDUxMixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gdmlzdWFsIHNpemUgdG8gZGlzcGxheSB0aWxlcyBmb3IgdGhpcyBsYXllci4gT25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBsYXllcnMuXCJcbiAgICB9LFxuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIk90aGVyIGtleXMgdG8gY29uZmlndXJlIHRoZSBkYXRhIHNvdXJjZS5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VfZ2VvanNvblwiOiB7XG4gICAgXCJ0eXBlXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJnZW9qc29uXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiZGF0YVwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCJcbiAgICB9XG4gIH0sXG4gIFwic291cmNlX3ZpZGVvXCI6IHtcbiAgICBcInR5cGVcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpZGVvXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidXJsXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIlVSTHMgdG8gdmlkZW8gY29udGVudCBpbiBvcmRlciBvZiBwcmVmZXJyZWQgZm9ybWF0LlwiXG4gICAgfSxcbiAgICBcImNvb3JkaW5hdGVzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcImxlbmd0aFwiOiA0LFxuICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIlxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgXCJsYXllclwiOiB7XG4gICAgXCJpZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiVW5pcXVlIGxheWVyIG5hbWUuXCJcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiZmlsbFwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJzeW1ib2xcIixcbiAgICAgICAgXCJyYXN0ZXJcIixcbiAgICAgICAgXCJiYWNrZ3JvdW5kXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlJlbmRlcmluZyB0eXBlIG9mIHRoaXMgbGF5ZXIuXCJcbiAgICB9LFxuICAgIFwicmVmXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJSZWZlcmVuY2VzIGFub3RoZXIgbGF5ZXIgdG8gY29weSBgdHlwZWAsIGBzb3VyY2VgLCBgc291cmNlLWxheWVyYCwgYG1pbnpvb21gLCBgbWF4em9vbWAsIGBmaWx0ZXJgLCBhbmQgYGxheW91dGAgcHJvcGVydGllcyBmcm9tLiBUaGlzIGFsbG93cyB0aGUgbGF5ZXJzIHRvIHNoYXJlIHByb2Nlc3NpbmcgYW5kIGJlIG1vcmUgZWZmaWNpZW50LlwiXG4gICAgfSxcbiAgICBcInNvdXJjZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTmFtZSBvZiBhIHNvdXJjZSBkZXNjcmlwdGlvbiB0byBiZSB1c2VkIGZvciB0aGlzIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZS1sYXllclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTGF5ZXIgdG8gdXNlIGZyb20gYSB2ZWN0b3IgdGlsZSBzb3VyY2UuIFJlcXVpcmVkIGlmIHRoZSBzb3VyY2Ugc3VwcG9ydHMgbXVsdGlwbGUgbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAyMixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbGF5ZXIgZ2V0cyBwYXJzZWQgYW5kIGFwcGVhcnMgb24uXCJcbiAgICB9LFxuICAgIFwibWF4em9vbVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWF4aW11bSB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsYXllciBnZXRzIHBhcnNlZCBhbmQgYXBwZWFycyBvbi5cIlxuICAgIH0sXG4gICAgXCJpbnRlcmFjdGl2ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRvY1wiOiBcIkVuYWJsZSBxdWVyeWluZyBvZiBmZWF0dXJlIGRhdGEgZnJvbSB0aGlzIGxheWVyIGZvciBpbnRlcmFjdGl2aXR5LlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlXG4gICAgfSxcbiAgICBcImZpbHRlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBleHByZXNzaW9uIHNwZWNpZnlpbmcgY29uZGl0aW9ucyBvbiBzb3VyY2UgZmVhdHVyZXMuIE9ubHkgZmVhdHVyZXMgdGhhdCBtYXRjaCB0aGUgZmlsdGVyIGFyZSBkaXNwbGF5ZWQuXCJcbiAgICB9LFxuICAgIFwibGF5b3V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImxheW91dFwiLFxuICAgICAgXCJkb2NcIjogXCJMYXlvdXQgcHJvcGVydGllcyBmb3IgdGhlIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInBhaW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkRlZmF1bHQgcGFpbnQgcHJvcGVydGllcyBmb3IgdGhpcyBsYXllci5cIlxuICAgIH0sXG4gICAgXCJwYWludC4qXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkNsYXNzLXNwZWNpZmljIHBhaW50IHByb3BlcnRpZXMgZm9yIHRoaXMgbGF5ZXIuIFRoZSBjbGFzcyBuYW1lIGlzIHRoZSBwYXJ0IGFmdGVyIHRoZSBmaXJzdCBkb3QuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0XCI6IFtcbiAgICBcImxheW91dF9maWxsXCIsXG4gICAgXCJsYXlvdXRfbGluZVwiLFxuICAgIFwibGF5b3V0X3N5bWJvbFwiLFxuICAgIFwibGF5b3V0X3Jhc3RlclwiLFxuICAgIFwibGF5b3V0X2JhY2tncm91bmRcIlxuICBdLFxuICBcImxheW91dF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9maWxsXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9saW5lXCI6IHtcbiAgICBcImxpbmUtY2FwXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJidXR0XCIsXG4gICAgICAgIFwicm91bmRcIixcbiAgICAgICAgXCJzcXVhcmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImJ1dHRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgbGluZSBlbmRpbmdzLlwiXG4gICAgfSxcbiAgICBcImxpbmUtam9pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiYmV2ZWxcIixcbiAgICAgICAgXCJyb3VuZFwiLFxuICAgICAgICBcIm1pdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJtaXRlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiBsaW5lcyB3aGVuIGpvaW5pbmcuXCJcbiAgICB9LFxuICAgIFwibGluZS1taXRlci1saW1pdFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJVc2VkIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCBtaXRlciBqb2lucyB0byBiZXZlbCBqb2lucyBmb3Igc2hhcnAgYW5nbGVzLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcImxpbmUtam9pblwiOiBcIm1pdGVyXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXJvdW5kLWxpbWl0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlVzZWQgdG8gYXV0b21hdGljYWxseSBjb252ZXJ0IHJvdW5kIGpvaW5zIHRvIG1pdGVyIGpvaW5zIGZvciBzaGFsbG93IGFuZ2xlcy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJsaW5lLWpvaW5cIjogXCJyb3VuZFwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3N5bWJvbFwiOiB7XG4gICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgICBcInBvaW50XCIsXG4gICAgICAgICAgXCJsaW5lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJwb2ludFwiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBwbGFjZW1lbnQgcmVsYXRpdmUgdG8gaXRzIGdlb21ldHJ5LiBgbGluZWAgY2FuIG9ubHkgYmUgdXNlZCBvbiBMaW5lU3RyaW5ncyBhbmQgUG9seWdvbnMuXCJcbiAgICB9LFxuICAgIFwic3ltYm9sLW1pbi1kaXN0YW5jZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyNTAsXG4gICAgICBcIm1pbmltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzeW1ib2wgYW5jaG9ycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IFwibGluZVwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwic3ltYm9sLWF2b2lkLWVkZ2VzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgIFwiZG9jXCI6IFwiSWYgdHJ1ZSwgdGhlIHN5bWJvbHMgd2lsbCBub3QgY3Jvc3MgdGlsZSBlZGdlcyB0byBhdm9pZCBtdXR1YWwgY29sbGlzaW9ucy4gUmVjb21tZW5kZWQgaW4gbGF5ZXJzIHRoYXQgZG9uJ3QgaGF2ZSBlbm91Z2ggcGFkZGluZyBpbiB0aGUgdmVjdG9yIHRpbGUgdG8gcHJldmVudCBjb2xsaXNpb25zLCBvciBpZiBpdCBpcyBhIHBvaW50IHN5bWJvbCBsYXllciBwbGFjZWQgYWZ0ZXIgYSBsaW5lIHN5bWJvbCBsYXllci5cIlxuICAgIH0sXG4gICAgXCJpY29uLWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCB0ZXh0LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taWdub3JlLXBsYWNlbWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIHdvbid0IGFmZmVjdCBwbGFjZW1lbnQgb2Ygb3RoZXIgaWNvbnMgYW5kIHRleHQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgaWNvbiwgaW4gc3BhY2VzIHdoZXJlIHRoZSBpY29uIHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIHdoZW4gbWFwIGlzIHJvdGF0ZWQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1tYXgtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIGZhY3RvciB0byBzY2FsZSB0aGUgaWNvbi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkb2NcIjogXCJBIHN0cmluZyB3aXRoIHt0b2tlbnN9IHJlcGxhY2VkLCByZWZlcmVuY2luZyB0aGUgZGF0YSBwcm9wZXJ0eSB0byBwdWxsIGZyb20uXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlXG4gICAgfSxcbiAgICBcImljb24tcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSBpY29uIGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCBpY29uIGJvdW5kaW5nIGJveCB0byBhdm9pZCBpY29uIGNvbGxpc2lvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1rZWVwLXVwcmlnaHRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiBtYXkgYmUgZmxpcHBlZCB0byBwcmV2ZW50IGl0IGZyb20gYmVpbmcgcmVuZGVyZWQgdXBzaWRlLWRvd25cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAge1xuICAgICAgICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSWNvbidzIG9mZnNldCBkaXN0YW5jZS4gVmFsdWVzIGFyZSBbeCwgeV0gd2hlcmUgbmVnYXRpdmVzIGluZGljYXRlIGxlZnQgYW5kIHVwLCByZXNwZWN0aXZlbHkuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIG9yIHRleHQgd2hlbiBtYXAgaXMgcm90YXRlZC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWZpZWxkXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJWYWx1ZSB0byB1c2UgZm9yIGEgdGV4dCBsYWJlbC4gRmVhdHVyZSBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdG9rZW5zIGxpa2Uge2ZpZWxkX25hbWV9LlwiXG4gICAgfSxcbiAgICBcInRleHQtZm9udFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIk9wZW4gU2FucyBSZWd1bGFyLCBBcmlhbCBVbmljb2RlIE1TIFJlZ3VsYXJcIixcbiAgICAgIFwiZG9jXCI6IFwiRm9udCBzdGFjayB0byB1c2UgZm9yIGRpc3BsYXlpbmcgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIHNpemUgdGV4dCB3aWxsIGJlIGxhaWQgb3V0LCB0byBjYWxjdWxhdGUgY29sbGlzaW9ucyB3aXRoLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtbWF4LXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE1LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gbGluZSB3aWR0aCBmb3IgdGV4dCB3cmFwcGluZy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEuMixcbiAgICAgIFwidW5pdHNcIjogXCJlbVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJUZXh0IGxlYWRpbmcgdmFsdWUgZm9yIG11bHRpLWxpbmUgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBrZXJuaW5nIHZhbHVlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtanVzdGlmeVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibGVmdFwiLFxuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcInJpZ2h0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJjZW50ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBqdXN0aWZpY2F0aW9uIG9wdGlvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcImxlZnRcIixcbiAgICAgICAgXCJyaWdodFwiLFxuICAgICAgICBcInRvcFwiLFxuICAgICAgICBcImJvdHRvbVwiLFxuICAgICAgICBcInRvcC1sZWZ0XCIsXG4gICAgICAgIFwidG9wLXJpZ2h0XCIsXG4gICAgICAgIFwiYm90dG9tLWxlZnRcIixcbiAgICAgICAgXCJib3R0b20tcmlnaHRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImNlbnRlclwiLFxuICAgICAgXCJkb2NcIjogXCJXaGljaCBwYXJ0IG9mIHRoZSB0ZXh0IHRvIHBsYWNlIGNsb3Nlc3QgdG8gdGhlIGFuY2hvci5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1hbmdsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiA0NSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIk1heGltdW0gYW5nbGUgY2hhbmdlIGJldHdlZW4gYWRqYWNlbnQgY2hhcmFjdGVycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwic3ltYm9sLXBsYWNlbWVudFwiOiBcImxpbmVcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSB0ZXh0IGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCB0ZXh0IGJvdW5kaW5nIGJveCB0byBhdm9pZCBsYWJlbCBjb2xsaXNpb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQta2VlcC11cHJpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCBtYXkgYmUgZmxpcHBlZCB2ZXJ0aWNhbGx5IHRvIHByZXZlbnQgaXQgZnJvbSBiZWluZyByZW5kZXJlZCB1cHNpZGUtZG93bi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNmb3JtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJub25lXCIsXG4gICAgICAgIFwidXBwZXJjYXNlXCIsXG4gICAgICAgIFwibG93ZXJjYXNlXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJub25lXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmllcyBob3cgdG8gY2FwaXRhbGl6ZSB0ZXh0LCBzaW1pbGFyIHRvIHRoZSBDU1MgYHRleHQtdHJhbnNmb3JtYCBwcm9wZXJ0eS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW9mZnNldFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGRpc3RhbmNlIHRoYXQgdGV4dCBpcyBvZmZzZXQgZnJvbSBpdHMgYW5jaG9yIGhvcml6b250YWxseSBhbmQgdmVydGljYWxseS5cIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwidW5pdHNcIjogXCJlbXNcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwXG4gICAgICBdLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtYWxsb3ctb3ZlcmxhcFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSB0ZXh0IHdpbGwgYmUgdmlzaWJsZSBldmVuIGlmIGl0IGNvbGxpZGVzIHdpdGggb3RoZXIgaWNvbnMgYW5kIGxhYmVscy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCB3b24ndCBhZmZlY3QgcGxhY2VtZW50IG9mIG90aGVyIGljb25zIGFuZCBsYWJlbHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgdGV4dCwgaW4gc3BhY2VzIHdoZXJlIHRoZSB0ZXh0IHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3Jhc3RlclwiOiB7XG4gICAgXCJ2aXNpYmlsaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJ2aXNpYmxlXCIsXG4gICAgICAgIFwibm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwidmlzaWJsZVwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiB0aGlzIGxheWVyLiBgbm9uZWAgaGlkZXMgdGhpcyBsYXllci5cIlxuICAgIH1cbiAgfSxcbiAgXCJmaWx0ZXJcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJ2YWx1ZVwiOiBcIipcIlxuICB9LFxuICBcImZpbHRlcl9vcGVyYXRvclwiOiB7XG4gICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgIFwidmFsdWVzXCI6IFtcbiAgICAgIFwiPT1cIixcbiAgICAgIFwiIT1cIixcbiAgICAgIFwiPlwiLFxuICAgICAgXCI+PVwiLFxuICAgICAgXCI8XCIsXG4gICAgICBcIjw9XCIsXG4gICAgICBcImluXCIsXG4gICAgICBcIiFpblwiLFxuICAgICAgXCJhbGxcIixcbiAgICAgIFwiYW55XCIsXG4gICAgICBcIm5vbmVcIlxuICAgIF1cbiAgfSxcbiAgXCJnZW9tZXRyeV90eXBlXCI6IHtcbiAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgXCJQb2ludFwiLFxuICAgICAgXCJMaW5lU3RyaW5nXCIsXG4gICAgICBcIlBvbHlnb25cIlxuICAgIF1cbiAgfSxcbiAgXCJmdW5jdGlvblwiOiB7XG4gICAgXCJzdG9wc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBhcnJheSBvZiBzdG9wcy5cIixcbiAgICAgIFwidmFsdWVcIjogXCJmdW5jdGlvbl9zdG9wXCJcbiAgICB9LFxuICAgIFwiYmFzZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIlRoZSBleHBvbmVudGlhbCBiYXNlIG9mIHRoZSBpbnRlcnBvbGF0aW9uIGN1cnZlLiBJdCBjb250cm9scyB0aGUgcmF0ZSBhdCB3aGljaCB0aGUgcmVzdWx0IGluY3JlYXNlcy4gSGlnaGVyIHZhbHVlcyBtYWtlIHRoZSByZXN1bHQgaW5jcmVhc2UgbW9yZSB0b3dhcmRzIHRoZSBoaWdoIGVuZCBvZiB0aGUgcmFuZ2UuIFdpdGggYDFgIHRoZSBzdG9wcyBhcmUgaW50ZXJwb2xhdGVkIGxpbmVhcmx5LlwiXG4gICAgfVxuICB9LFxuICBcImZ1bmN0aW9uX3N0b3BcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgIFwidmFsdWVcIjogW1xuICAgICAgXCJudW1iZXJcIixcbiAgICAgIFwiY29sb3JcIlxuICAgIF0sXG4gICAgXCJsZW5ndGhcIjogMixcbiAgICBcImRvY1wiOiBcIlpvb20gbGV2ZWwgYW5kIHZhbHVlIHBhaXIuXCJcbiAgfSxcbiAgXCJwYWludFwiOiBbXG4gICAgXCJwYWludF9maWxsXCIsXG4gICAgXCJwYWludF9saW5lXCIsXG4gICAgXCJwYWludF9zeW1ib2xcIixcbiAgICBcInBhaW50X3Jhc3RlclwiLFxuICAgIFwicGFpbnRfYmFja2dyb3VuZFwiXG4gIF0sXG4gIFwicGFpbnRfZmlsbFwiOiB7XG4gICAgXCJmaWxsLWFudGlhbGlhc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiV2hldGhlciBvciBub3QgdGhlIGZpbGwgc2hvdWxkIGJlIGFudGlhbGlhc2VkLlwiXG4gICAgfSxcbiAgICBcImZpbGwtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgZ2l2ZW4gdG8gdGhlIGZpbGwgY29sb3IuXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJmaWxsLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBjb2xvciBvZiB0aGUgZmlsbC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLW91dGxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG91dGxpbmUgY29sb3Igb2YgdGhlIGZpbGwuIE1hdGNoZXMgdGhlIHZhbHVlIG9mIGBmaWxsLWNvbG9yYCBpZiB1bnNwZWNpZmllZC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIFwiZmlsbC1hbnRpYWxpYXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZ2VvbWV0cnkncyBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiZmlsbC10cmFuc2xhdGVcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBmaWxscy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9saW5lXCI6IHtcbiAgICBcImxpbmUtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGdlb21ldHJ5J3Mgb2Zmc2V0LiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImxpbmUtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwibGluZS13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiU3Ryb2tlIHRoaWNrbmVzcy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWdhcC13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIkRyYXdzIGEgbGluZSBjYXNpbmcgb3V0c2lkZSBvZiBhIGxpbmUncyBhY3R1YWwgcGF0aC4gVmFsdWUgaW5kaWNhdGVzIHRoZSB3aWR0aCBvZiB0aGUgaW5uZXIgZ2FwLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCJcbiAgICB9LFxuICAgIFwibGluZS1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJCbHVyIGFwcGxpZWQgdG8gdGhlIGxpbmUsIGluIHBpeGVscy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWRhc2hhcnJheVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGxlbmd0aHMgb2YgdGhlIGFsdGVybmF0aW5nIGRhc2hlcyBhbmQgZ2FwcyB0aGF0IGZvcm0gdGhlIGRhc2ggcGF0dGVybi4gVGhlIGxlbmd0aHMgYXJlIGxhdGVyIHNjYWxlZCBieSB0aGUgbGluZSB3aWR0aC4gVG8gY29udmVydCBhIGRhc2ggbGVuZ3RoIHRvIHBpeGVscywgbXVsdGlwbHkgdGhlIGxlbmd0aCBieSB0aGUgY3VycmVudCBsaW5lIHdpZHRoLlwiLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJsaW5lIHdpZHRoc1wiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBsaW5lcy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9zeW1ib2xcIjoge1xuICAgIFwiaWNvbi1vcGFjaXR5XCI6IHtcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGljb24gd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiU2NhbGUgZmFjdG9yIGZvciBpY29uLiAxIGlzIG9yaWdpbmFsIHNpemUsIDMgdHJpcGxlcyB0aGUgc2l6ZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uLiBUaGlzIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBzZGYgaWNvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uJ3MgaGFsby4gSWNvbiBoYWxvcyBjYW4gb25seSBiZSB1c2VkIHdpdGggc2RmIGljb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiRGlzdGFuY2Ugb2YgaGFsbyB0byB0aGUgaWNvbiBvdXRsaW5lLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIG91dCB0aGUgaGFsbyB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBpY29uJ3Mgb2Zmc2V0IGRpc3RhbmNlLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJpY29uLXRyYW5zbGF0ZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIHRleHQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxNixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIkZvbnQgc2l6ZS4gSWYgdW5zcGVjaWZpZWQsIHRoZSB0ZXh0IHdpbGwgYmUgYXMgYmlnIGFzIGFsbG93ZWQgYnkgdGhlIGxheWVyIGRlZmluaXRpb24uXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgY29sb3Igd2l0aCB3aGljaCB0aGUgdGV4dCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiIzAwMDAwMFwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSB0ZXh0J3MgaGFsbywgd2hpY2ggaGVscHMgaXQgc3RhbmQgb3V0IGZyb20gYmFja2dyb3VuZHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJEaXN0YW5jZSBvZiBoYWxvIHRvIHRoZSBmb250IG91dGxpbmUuIE1heCB0ZXh0IGhhbG8gd2lkdGggaXMgMS80IG9mIHRoZSBmb250LXNpemUuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWJsdXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBoYWxvJ3MgZmFkZW91dCBkaXN0YW5jZSB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiLFxuICAgICAgICBcInRleHQtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9XG4gIH0sXG4gIFwicGFpbnRfcmFzdGVyXCI6IHtcbiAgICBcInJhc3Rlci1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgaW1hZ2Ugd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcInJhc3Rlci1odWUtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImRvY1wiOiBcIlJvdGF0ZXMgaHVlcyBhcm91bmQgdGhlIGNvbG9yIHdoZWVsLlwiXG4gICAgfSxcbiAgICBcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSW5jcmVhc2Ugb3IgcmVkdWNlIHRoZSBicmlnaHRuZXNzIG9mIHRoZSBpbWFnZS4gVGhlIHZhbHVlIGlzIHRoZSBtaW5pbXVtIGJyaWdodG5lc3MuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgYnJpZ2h0bmVzcyBvZiB0aGUgaW1hZ2UuIFRoZSB2YWx1ZSBpcyB0aGUgbWF4aW11bSBicmlnaHRuZXNzLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLXNhdHVyYXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgc2F0dXJhdGlvbiBvZiB0aGUgaW1hZ2UuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAtMSxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLWNvbnRyYXN0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJJbmNyZWFzZSBvciByZWR1Y2UgdGhlIGNvbnRyYXN0IG9mIHRoZSBpbWFnZS5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IC0xLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIGR1cmF0aW9uIHdoZW4gYSBuZXcgdGlsZSBpcyBhZGRlZC5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcImJhY2tncm91bmQtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGJhY2tncm91bmQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJiYWNrZ3JvdW5kLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJiYWNrZ3JvdW5kLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk9wdGlvbmFsbHkgYW4gaW1hZ2Ugd2hpY2ggaXMgZHJhd24gYXMgdGhlIGJhY2tncm91bmQuXCJcbiAgICB9LFxuICAgIFwiYmFja2dyb3VuZC1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgYmFja2dyb3VuZCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9XG4gIH0sXG4gIFwidHJhbnNpdGlvblwiOiB7XG4gICAgXCJkdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwidW5pdHNcIjogXCJtaWxsaXNlY29uZHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGltZSBhbGxvdHRlZCBmb3IgdHJhbnNpdGlvbnMgdG8gY29tcGxldGUuXCJcbiAgICB9LFxuICAgIFwiZGVsYXlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJMZW5ndGggb2YgdGltZSBiZWZvcmUgYSB0cmFuc2l0aW9uIGJlZ2lucy5cIlxuICAgIH1cbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBsaWdodHdlaWdodCBCdWZmZXIgc2hpbSBmb3IgcGJmIGJyb3dzZXIgYnVpbGRcbi8vIGJhc2VkIG9uIGNvZGUgZnJvbSBnaXRodWIuY29tL2Zlcm9zcy9idWZmZXIgKE1JVC1saWNlbnNlZClcblxubW9kdWxlLmV4cG9ydHMgPSBCdWZmZXI7XG5cbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpO1xuXG52YXIgQnVmZmVyTWV0aG9kcztcblxuZnVuY3Rpb24gQnVmZmVyKGxlbmd0aCkge1xuICAgIHZhciBhcnI7XG4gICAgaWYgKGxlbmd0aCAmJiBsZW5ndGgubGVuZ3RoKSB7XG4gICAgICAgIGFyciA9IGxlbmd0aDtcbiAgICAgICAgbGVuZ3RoID0gYXJyLmxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCB8fCAwKTtcbiAgICBpZiAoYXJyKSBidWYuc2V0KGFycik7XG5cbiAgICBidWYucmVhZFVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkVUludDMyTEU7XG4gICAgYnVmLndyaXRlVUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG4gICAgYnVmLnJlYWRJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkSW50MzJMRTtcbiAgICBidWYud3JpdGVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEU7XG4gICAgYnVmLnJlYWRGbG9hdExFID0gQnVmZmVyTWV0aG9kcy5yZWFkRmxvYXRMRTtcbiAgICBidWYud3JpdGVGbG9hdExFID0gQnVmZmVyTWV0aG9kcy53cml0ZUZsb2F0TEU7XG4gICAgYnVmLnJlYWREb3VibGVMRSA9IEJ1ZmZlck1ldGhvZHMucmVhZERvdWJsZUxFO1xuICAgIGJ1Zi53cml0ZURvdWJsZUxFID0gQnVmZmVyTWV0aG9kcy53cml0ZURvdWJsZUxFO1xuICAgIGJ1Zi50b1N0cmluZyA9IEJ1ZmZlck1ldGhvZHMudG9TdHJpbmc7XG4gICAgYnVmLndyaXRlID0gQnVmZmVyTWV0aG9kcy53cml0ZTtcbiAgICBidWYuc2xpY2UgPSBCdWZmZXJNZXRob2RzLnNsaWNlO1xuICAgIGJ1Zi5jb3B5ID0gQnVmZmVyTWV0aG9kcy5jb3B5O1xuXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWU7XG4gICAgcmV0dXJuIGJ1Zjtcbn1cblxudmFyIGxhc3RTdHIsIGxhc3RTdHJFbmNvZGVkO1xuXG5CdWZmZXJNZXRob2RzID0ge1xuICAgIHJlYWRVSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSAqIDB4MTAwMDAwMCk7XG4gICAgfSxcblxuICAgIHdyaXRlVUludDMyTEU6IGZ1bmN0aW9uKHZhbCwgcG9zKSB7XG4gICAgICAgIHRoaXNbcG9zXSA9IHZhbDtcbiAgICAgICAgdGhpc1twb3MgKyAxXSA9ICh2YWwgPj4+IDgpO1xuICAgICAgICB0aGlzW3BvcyArIDJdID0gKHZhbCA+Pj4gMTYpO1xuICAgICAgICB0aGlzW3BvcyArIDNdID0gKHZhbCA+Pj4gMjQpO1xuICAgIH0sXG5cbiAgICByZWFkSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSA8PCAyNCk7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdExFOiAgZnVuY3Rpb24ocG9zKSB7IHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgcmVhZERvdWJsZUxFOiBmdW5jdGlvbihwb3MpIHsgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHdyaXRlRmxvYXRMRTogIGZ1bmN0aW9uKHZhbCwgcG9zKSB7IHJldHVybiBpZWVlNzU0LndyaXRlKHRoaXMsIHZhbCwgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgd3JpdGVEb3VibGVMRTogZnVuY3Rpb24odmFsLCBwb3MpIHsgcmV0dXJuIGllZWU3NTQud3JpdGUodGhpcywgdmFsLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHRvU3RyaW5nOiBmdW5jdGlvbihlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICAgICAgICB2YXIgc3RyID0gJycsXG4gICAgICAgICAgICB0bXAgPSAnJztcblxuICAgICAgICBzdGFydCA9IHN0YXJ0IHx8IDA7XG4gICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGVuZ3RoLCBlbmQgfHwgdGhpcy5sZW5ndGgpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2ggPSB0aGlzW2ldO1xuICAgICAgICAgICAgaWYgKGNoIDw9IDB4N0YpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gZGVjb2RlVVJJQ29tcG9uZW50KHRtcCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTtcbiAgICAgICAgICAgICAgICB0bXAgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG1wICs9ICclJyArIGNoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0ciArPSBkZWNvZGVVUklDb21wb25lbnQodG1wKTtcblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICB3cml0ZTogZnVuY3Rpb24oc3RyLCBwb3MpIHtcbiAgICAgICAgdmFyIGJ5dGVzID0gc3RyID09PSBsYXN0U3RyID8gbGFzdFN0ckVuY29kZWQgOiBlbmNvZGVTdHJpbmcoc3RyKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpc1twb3MgKyBpXSA9IGJ5dGVzW2ldO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNsaWNlOiBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpO1xuICAgIH0sXG5cbiAgICBjb3B5OiBmdW5jdGlvbihidWYsIHBvcykge1xuICAgICAgICBwb3MgPSBwb3MgfHwgMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBidWZbcG9zICsgaV0gPSB0aGlzW2ldO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgbGFzdFN0ciA9IHN0cjtcbiAgICBsYXN0U3RyRW5jb2RlZCA9IGVuY29kZVN0cmluZyhzdHIpO1xuICAgIHJldHVybiBsYXN0U3RyRW5jb2RlZC5sZW5ndGg7XG59O1xuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbihidWYpIHtcbiAgICByZXR1cm4gISEoYnVmICYmIGJ1Zi5faXNCdWZmZXIpO1xufTtcblxuZnVuY3Rpb24gZW5jb2RlU3RyaW5nKHN0cikge1xuICAgIHZhciBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICBieXRlcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGMsIGxlYWQ7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSk7IC8vIGNvZGUgcG9pbnRcblxuICAgICAgICBpZiAoYyA+IDB4RDdGRiAmJiBjIDwgMHhFMDAwKSB7XG5cbiAgICAgICAgICAgIGlmIChsZWFkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGMgPCAweERDMDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IGM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYyA9IGxlYWQgLSAweEQ4MDAgPDwgMTAgfCBjIC0gMHhEQzAwIHwgMHgxMDAwMDtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjID4gMHhEQkZGIHx8IChpICsgMSA9PT0gbGVuZ3RoKSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICBlbHNlIGxlYWQgPSBjO1xuXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmIChsZWFkKSB7XG4gICAgICAgICAgICBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpO1xuICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODApIGJ5dGVzLnB1c2goYyk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDgwMCkgYnl0ZXMucHVzaChjID4+IDB4NiB8IDB4QzAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDEwMDAwKSBieXRlcy5wdXNoKGMgPj4gMHhDIHwgMHhFMCwgYyA+PiAweDYgJiAweDNGIHwgMHg4MCwgYyAmIDB4M0YgfCAweDgwKTtcbiAgICAgICAgZWxzZSBieXRlcy5wdXNoKGMgPj4gMHgxMiB8IDB4RjAsIGMgPj4gMHhDICYgMHgzRiB8IDB4ODAsIGMgPj4gMHg2ICYgMHgzRiB8IDB4ODAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgfVxuICAgIHJldHVybiBieXRlcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBQYmY7XG5cbnZhciBCdWZmZXIgPSBnbG9iYWwuQnVmZmVyIHx8IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbmZ1bmN0aW9uIFBiZihidWYpIHtcbiAgICB0aGlzLmJ1ZiA9ICFCdWZmZXIuaXNCdWZmZXIoYnVmKSA/IG5ldyBCdWZmZXIoYnVmIHx8IDApIDogYnVmO1xuICAgIHRoaXMucG9zID0gMDtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMuYnVmLmxlbmd0aDtcbn1cblxuUGJmLlZhcmludCAgPSAwOyAvLyB2YXJpbnQ6IGludDMyLCBpbnQ2NCwgdWludDMyLCB1aW50NjQsIHNpbnQzMiwgc2ludDY0LCBib29sLCBlbnVtXG5QYmYuRml4ZWQ2NCA9IDE7IC8vIDY0LWJpdDogZG91YmxlLCBmaXhlZDY0LCBzZml4ZWQ2NFxuUGJmLkJ5dGVzICAgPSAyOyAvLyBsZW5ndGgtZGVsaW1pdGVkOiBzdHJpbmcsIGJ5dGVzLCBlbWJlZGRlZCBtZXNzYWdlcywgcGFja2VkIHJlcGVhdGVkIGZpZWxkc1xuUGJmLkZpeGVkMzIgPSA1OyAvLyAzMi1iaXQ6IGZsb2F0LCBmaXhlZDMyLCBzZml4ZWQzMlxuXG52YXIgU0hJRlRfTEVGVF8zMiA9ICgxIDw8IDE2KSAqICgxIDw8IDE2KSxcbiAgICBTSElGVF9SSUdIVF8zMiA9IDEgLyBTSElGVF9MRUZUXzMyLFxuICAgIFBPV18yXzYzID0gTWF0aC5wb3coMiwgNjMpO1xuXG5QYmYucHJvdG90eXBlID0ge1xuXG4gICAgZGVzdHJveTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuYnVmID0gbnVsbDtcbiAgICB9LFxuXG4gICAgLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHJlYWRGaWVsZHM6IGZ1bmN0aW9uKHJlYWRGaWVsZCwgcmVzdWx0LCBlbmQpIHtcbiAgICAgICAgZW5kID0gZW5kIHx8IHRoaXMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludCgpLFxuICAgICAgICAgICAgICAgIHRhZyA9IHZhbCA+PiAzLFxuICAgICAgICAgICAgICAgIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG5cbiAgICAgICAgICAgIHJlYWRGaWVsZCh0YWcsIHJlc3VsdCwgdGhpcyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gc3RhcnRQb3MpIHRoaXMuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIHJlYWRNZXNzYWdlOiBmdW5jdGlvbihyZWFkRmllbGQsIHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkRmllbGRzKHJlYWRGaWVsZCwgcmVzdWx0LCB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zKTtcbiAgICB9LFxuXG4gICAgcmVhZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZFVJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFNGaXhlZDMyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgLy8gNjQtYml0IGludCBoYW5kbGluZyBpcyBiYXNlZCBvbiBnaXRodWIuY29tL2Rwdy9ub2RlLWJ1ZmZlci1tb3JlLWludHMgKE1JVC1saWNlbnNlZClcblxuICAgIHJlYWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRVSW50MzJMRSh0aGlzLnBvcykgKyB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRTRml4ZWQ2NDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MpICsgdGhpcy5idWYucmVhZEludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkRmxvYXRMRSh0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZERvdWJsZUxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBidWYgPSB0aGlzLmJ1ZixcbiAgICAgICAgICAgIHZhbCwgYiwgYjAsIGIxLCBiMiwgYjM7XG5cbiAgICAgICAgYjAgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMCA8IDB4ODApIHJldHVybiBiMDsgICAgICAgICAgICAgICAgIGIwID0gYjAgJiAweDdmO1xuICAgICAgICBiMSA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIxIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgPDwgNzsgICAgICAgYjEgPSAoYjEgJiAweDdmKSA8PCA3O1xuICAgICAgICBiMiA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIyIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgfCBiMiA8PCAxNDsgYjIgPSAoYjIgJiAweDdmKSA8PCAxNDtcbiAgICAgICAgYjMgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMyA8IDB4ODApIHJldHVybiBiMCB8IGIxIHwgYjIgfCBiMyA8PCAyMTtcblxuICAgICAgICB2YWwgPSBiMCB8IGIxIHwgYjIgfCAoYjMgJiAweDdmKSA8PCAyMTtcblxuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDA7ICAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwOyAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4NDAwMDAwMDAwMDA7ICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MjAwMDAwMDAwMDAwMDsgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDAwMDAwMDAwOyAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwMDAwMDAwMDsgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgdmFyaW50IG5vdCBtb3JlIHRoYW4gMTAgYnl0ZXMnKTtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICB2YWwgPSB0aGlzLnJlYWRWYXJpbnQoKTtcblxuICAgICAgICBpZiAodmFsIDwgUE9XXzJfNjMpIHJldHVybiB2YWw7XG5cbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zIC0gMjtcbiAgICAgICAgd2hpbGUgKHRoaXMuYnVmW3Bvc10gPT09IDB4ZmYpIHBvcy0tO1xuICAgICAgICBpZiAocG9zIDwgc3RhcnRQb3MpIHBvcyA9IHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhbCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zIC0gc3RhcnRQb3MgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBiID0gfnRoaXMuYnVmW3N0YXJ0UG9zICsgaV0gJiAweDdmO1xuICAgICAgICAgICAgdmFsICs9IGkgPCA0ID8gYiA8PCBpICogNyA6IGIgKiBNYXRoLnBvdygyLCBpICogNyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLXZhbCAtIDE7XG4gICAgfSxcblxuICAgIHJlYWRTVmFyaW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG51bSA9IHRoaXMucmVhZFZhcmludCgpO1xuICAgICAgICByZXR1cm4gbnVtICUgMiA9PT0gMSA/IChudW0gKyAxKSAvIC0yIDogbnVtIC8gMjsgLy8gemlnemFnIGVuY29kaW5nXG4gICAgfSxcblxuICAgIHJlYWRCb29sZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpO1xuICAgIH0sXG5cbiAgICByZWFkU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBzdHIgPSB0aGlzLmJ1Zi50b1N0cmluZygndXRmOCcsIHRoaXMucG9zLCBlbmQpO1xuICAgICAgICB0aGlzLnBvcyA9IGVuZDtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuXG4gICAgcmVhZEJ5dGVzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBidWZmZXIgPSB0aGlzLmJ1Zi5zbGljZSh0aGlzLnBvcywgZW5kKTtcbiAgICAgICAgdGhpcy5wb3MgPSBlbmQ7XG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfSxcblxuICAgIC8vIHZlcmJvc2UgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnM7IGRvZXNuJ3QgYWZmZWN0IGd6aXBwZWQgc2l6ZVxuXG4gICAgcmVhZFBhY2tlZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRWYXJpbnQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU1ZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEJvb2xlYW46IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkQm9vbGVhbigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRGbG9hdCgpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRG91YmxlKCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsIGFyciA9IFtdO1xuICAgICAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcblxuICAgIHNraXA6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHZhbCAmIDB4NztcbiAgICAgICAgaWYgKHR5cGUgPT09IFBiZi5WYXJpbnQpIHdoaWxlICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA+IDB4N2YpIHt9XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT09IFBiZi5CeXRlcykgdGhpcy5wb3MgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zO1xuICAgICAgICBlbHNlIGlmICh0eXBlID09PSBQYmYuRml4ZWQzMikgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkNjQpIHRoaXMucG9zICs9IDg7XG4gICAgICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdVbmltcGxlbWVudGVkIHR5cGU6ICcgKyB0eXBlKTtcbiAgICB9LFxuXG4gICAgLy8gPT09IFdSSVRJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHdyaXRlVGFnOiBmdW5jdGlvbih0YWcsIHR5cGUpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludCgodGFnIDw8IDMpIHwgdHlwZSk7XG4gICAgfSxcblxuICAgIHJlYWxsb2M6IGZ1bmN0aW9uKG1pbikge1xuICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfHwgMTY7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aCA8IHRoaXMucG9zICsgbWluKSBsZW5ndGggKj0gMjtcblxuICAgICAgICBpZiAobGVuZ3RoICE9PSB0aGlzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYnVmLmNvcHkoYnVmKTtcbiAgICAgICAgICAgIHRoaXMuYnVmID0gYnVmO1xuICAgICAgICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZmluaXNoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLnBvcztcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcy5idWYuc2xpY2UoMCwgdGhpcy5sZW5ndGgpO1xuICAgIH0sXG5cbiAgICB3cml0ZUZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlVUludDMyTEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlU0ZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRSh2YWwsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICB9LFxuXG4gICAgd3JpdGVGaXhlZDY0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUludDMyTEUodmFsICYgLTEsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVVSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVTRml4ZWQ2NDogZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVJbnQzMkxFKHZhbCAmIC0xLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YWwgPSArdmFsO1xuXG4gICAgICAgIGlmICh2YWwgPD0gMHg3Zikge1xuICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWw7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgzZmZmKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2MoMik7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAwKSAmIDB4N2YpIHwgMHg4MDtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDcpICYgMHg3Zik7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgxZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygzKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHZhbCA8PSAweGZmZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYyg0KTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAyMSkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zO1xuICAgICAgICAgICAgd2hpbGUgKHZhbCA+PSAweDgwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKHZhbCAmIDB4ZmYpIHwgMHg4MDtcbiAgICAgICAgICAgICAgICB2YWwgLz0gMHg4MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygxKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gdmFsIHwgMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyAtIHBvcyA+IDEwKSB0aHJvdyBuZXcgRXJyb3IoJ0dpdmVuIHZhcmludCBkb2VzblxcJ3QgZml0IGludG8gMTAgYnl0ZXMnKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZVNWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCA8IDAgPyAtdmFsICogMiAtIDEgOiB2YWwgKiAyKTtcbiAgICB9LFxuXG4gICAgd3JpdGVCb29sZWFuOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludChCb29sZWFuKHZhbCkpO1xuICAgIH0sXG5cbiAgICB3cml0ZVN0cmluZzogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgIHN0ciA9IFN0cmluZyhzdHIpO1xuICAgICAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuYnl0ZUxlbmd0aChzdHIpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KGJ5dGVzKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGJ5dGVzKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGUoc3RyLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IGJ5dGVzO1xuICAgIH0sXG5cbiAgICB3cml0ZUZsb2F0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUZsb2F0TEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlRG91YmxlOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZURvdWJsZUxFKHZhbCwgdGhpcy5wb3MpO1xuICAgICAgICB0aGlzLnBvcyArPSA4O1xuICAgIH0sXG5cbiAgICB3cml0ZUJ5dGVzOiBmdW5jdGlvbihidWZmZXIpIHtcbiAgICAgICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGxlbik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHRoaXMuYnVmW3RoaXMucG9zKytdID0gYnVmZmVyW2ldO1xuICAgIH0sXG5cbiAgICB3cml0ZU1lc3NhZ2U6IGZ1bmN0aW9uKHRhZywgZm4sIG9iaikge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkJ5dGVzKTtcblxuICAgICAgICB0aGlzLnBvcysrOyAvLyByZXNlcnZlIDEgYnl0ZSBmb3Igc2hvcnQgbWVzc2FnZSBsZW5ndGhcblxuICAgICAgICAvLyB3cml0ZSB0aGUgbWVzc2FnZSBkaXJlY3RseSB0byB0aGUgYnVmZmVyIGFuZCBzZWUgaG93IG11Y2ggd2FzIHdyaXR0ZW5cbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG4gICAgICAgIGZuKG9iaiwgdGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLnBvcyAtIHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhciB2YXJpbnRMZW4gPVxuICAgICAgICAgICAgbGVuIDw9IDB4N2YgPyAxIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDNmZmYgPyAyIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDFmZmZmZiA/IDMgOlxuICAgICAgICAgICAgbGVuIDw9IDB4ZmZmZmZmZiA/IDQgOiBNYXRoLmNlaWwoTWF0aC5sb2cobGVuKSAvIChNYXRoLkxOMiAqIDcpKTtcblxuICAgICAgICAvLyBpZiAxIGJ5dGUgaXNuJ3QgZW5vdWdoIGZvciBlbmNvZGluZyBtZXNzYWdlIGxlbmd0aCwgc2hpZnQgdGhlIGRhdGEgdG8gdGhlIHJpZ2h0XG4gICAgICAgIGlmICh2YXJpbnRMZW4gPiAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2ModmFyaW50TGVuIC0gMSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5wb3MgLSAxOyBpID49IHN0YXJ0UG9zOyBpLS0pIHRoaXMuYnVmW2kgKyB2YXJpbnRMZW4gLSAxXSA9IHRoaXMuYnVmW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluYWxseSwgd3JpdGUgdGhlIG1lc3NhZ2UgbGVuZ3RoIGluIHRoZSByZXNlcnZlZCBwbGFjZSBhbmQgcmVzdG9yZSB0aGUgcG9zaXRpb25cbiAgICAgICAgdGhpcy5wb3MgPSBzdGFydFBvcyAtIDE7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gbGVuO1xuICAgIH0sXG5cbiAgICB3cml0ZVBhY2tlZFZhcmludDogICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkVmFyaW50LCBhcnIpOyAgIH0sXG4gICAgd3JpdGVQYWNrZWRTVmFyaW50OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZFNWYXJpbnQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkQm9vbGVhbjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRCb29sZWFuLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZEZsb2F0OiAgICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkRmxvYXQsIGFycik7ICAgIH0sXG4gICAgd3JpdGVQYWNrZWREb3VibGU6ICAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZERvdWJsZSwgYXJyKTsgICB9LFxuICAgIHdyaXRlUGFja2VkRml4ZWQzMjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRGaXhlZDMyLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZFNGaXhlZDMyOiBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkU0ZpeGVkMzIsIGFycik7IH0sXG4gICAgd3JpdGVQYWNrZWRGaXhlZDY0OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZEZpeGVkNjQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRTRml4ZWQ2NCwgYXJyKTsgfSxcblxuICAgIHdyaXRlQnl0ZXNGaWVsZDogZnVuY3Rpb24odGFnLCBidWZmZXIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVCeXRlcyhidWZmZXIpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDMyKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQzMih2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDY0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQ2NCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlU1ZhcmludCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVTdHJpbmdGaWVsZDogZnVuY3Rpb24odGFnLCBzdHIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVTdHJpbmcoc3RyKTtcbiAgICB9LFxuICAgIHdyaXRlRmxvYXRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDMyKTtcbiAgICAgICAgdGhpcy53cml0ZUZsb2F0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZURvdWJsZUZpZWxkOiBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkNjQpO1xuICAgICAgICB0aGlzLndyaXRlRG91YmxlKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZUJvb2xlYW5GaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludEZpZWxkKHRhZywgQm9vbGVhbih2YWwpKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiB3cml0ZVBhY2tlZFZhcmludChhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVWYXJpbnQoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNWYXJpbnQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTVmFyaW50KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZsb2F0KGFyciwgcGJmKSAgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGbG9hdChhcnJbaV0pOyAgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZERvdWJsZShhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVEb3VibGUoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEJvb2xlYW4oYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVCb29sZWFuKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkMzIoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDMyKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDMyKGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQzMihhcnJbaV0pOyB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkNjQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDY0KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDY0KGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQ2NChhcnJbaV0pOyB9XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBvaW50O1xuXG5mdW5jdGlvbiBQb2ludCh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xufVxuXG5Qb2ludC5wcm90b3R5cGUgPSB7XG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgdGhpcy55KTsgfSxcblxuICAgIGFkZDogICAgIGZ1bmN0aW9uKHApIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHApOyAgICAgfSxcbiAgICBzdWI6ICAgICBmdW5jdGlvbihwKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3N1YihwKTsgICAgIH0sXG4gICAgbXVsdDogICAgZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0KGspOyAgICB9LFxuICAgIGRpdjogICAgIGZ1bmN0aW9uKGspIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2KGspOyAgICAgfSxcbiAgICByb3RhdGU6ICBmdW5jdGlvbihhKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZShhKTsgIH0sXG4gICAgbWF0TXVsdDogZnVuY3Rpb24obSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tYXRNdWx0KG0pOyB9LFxuICAgIHVuaXQ6ICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCk7IH0sXG4gICAgcGVycDogICAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKTsgfSxcbiAgICByb3VuZDogICBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTsgfSxcblxuICAgIG1hZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQodGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55KTtcbiAgICB9LFxuXG4gICAgZXF1YWxzOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnggPT09IHAueCAmJlxuICAgICAgICAgICAgICAgdGhpcy55ID09PSBwLnk7XG4gICAgfSxcblxuICAgIGRpc3Q6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIocCkpO1xuICAgIH0sXG5cbiAgICBkaXN0U3FyOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHZhciBkeCA9IHAueCAtIHRoaXMueCxcbiAgICAgICAgICAgIGR5ID0gcC55IC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG4gICAgfSxcblxuICAgIGFuZ2xlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpO1xuICAgIH0sXG5cbiAgICBhbmdsZVRvOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMueSAtIGIueSwgdGhpcy54IC0gYi54KTtcbiAgICB9LFxuXG4gICAgYW5nbGVXaXRoOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFuZ2xlV2l0aFNlcChiLngsIGIueSk7XG4gICAgfSxcblxuICAgIC8vIEZpbmQgdGhlIGFuZ2xlIG9mIHRoZSB0d28gdmVjdG9ycywgc29sdmluZyB0aGUgZm9ybXVsYSBmb3IgdGhlIGNyb3NzIHByb2R1Y3QgYSB4IGIgPSB8YXx8YnxzaW4ozrgpIGZvciDOuC5cbiAgICBhbmdsZVdpdGhTZXA6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoXG4gICAgICAgICAgICB0aGlzLnggKiB5IC0gdGhpcy55ICogeCxcbiAgICAgICAgICAgIHRoaXMueCAqIHggKyB0aGlzLnkgKiB5KTtcbiAgICB9LFxuXG4gICAgX21hdE11bHQ6IGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgdmFyIHggPSBtWzBdICogdGhpcy54ICsgbVsxXSAqIHRoaXMueSxcbiAgICAgICAgICAgIHkgPSBtWzJdICogdGhpcy54ICsgbVszXSAqIHRoaXMueTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hZGQ6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54ICs9IHAueDtcbiAgICAgICAgdGhpcy55ICs9IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9zdWI6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54IC09IHAueDtcbiAgICAgICAgdGhpcy55IC09IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9tdWx0OiBmdW5jdGlvbihrKSB7XG4gICAgICAgIHRoaXMueCAqPSBrO1xuICAgICAgICB0aGlzLnkgKj0gaztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kaXY6IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdGhpcy54IC89IGs7XG4gICAgICAgIHRoaXMueSAvPSBrO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3VuaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9kaXYodGhpcy5tYWcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcGVycDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55O1xuICAgICAgICB0aGlzLnkgPSB0aGlzLng7XG4gICAgICAgIHRoaXMueCA9IC15O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdGF0ZTogZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgICAgIHggPSBjb3MgKiB0aGlzLnggLSBzaW4gKiB0aGlzLnksXG4gICAgICAgICAgICB5ID0gc2luICogdGhpcy54ICsgY29zICogdGhpcy55O1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgUG9pbnQgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblBvaW50LmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoYVswXSwgYVsxXSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufTtcbiIsIi8qXG4gKGMpIDIwMTMsIFZsYWRpbWlyIEFnYWZvbmtpblxuIFJCdXNoLCBhIEphdmFTY3JpcHQgbGlicmFyeSBmb3IgaGlnaC1wZXJmb3JtYW5jZSAyRCBzcGF0aWFsIGluZGV4aW5nIG9mIHBvaW50cyBhbmQgcmVjdGFuZ2xlcy5cbiBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9yYnVzaFxuKi9cblxuKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpIHtcblxuICAgIC8vIGpzaGludCBuZXdjYXA6IGZhbHNlLCB2YWxpZHRoaXM6IHRydWVcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgcmJ1c2gpKSByZXR1cm4gbmV3IHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCk7XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgICB0b0JCb3ggPSB0aGlzLnRvQkJveDtcblxuICAgICAgICBpZiAoIWludGVyc2VjdHMoYmJveCwgbm9kZS5iYm94KSkgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICB2YXIgbm9kZXNUb1NlYXJjaCA9IFtdLFxuICAgICAgICAgICAgaSwgbGVuLCBjaGlsZCwgY2hpbGRCQm94O1xuXG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgY2hpbGRCQm94ID0gbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3g7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJzZWN0cyhiYm94LCBjaGlsZEJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGFpbnMoYmJveCwgY2hpbGRCQm94KSkgdGhpcy5fYWxsKGNoaWxkLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBjb2xsaWRlczogZnVuY3Rpb24gKGJib3gpIHtcblxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZGF0YSxcbiAgICAgICAgICAgIHRvQkJveCA9IHRoaXMudG9CQm94O1xuXG4gICAgICAgIGlmICghaW50ZXJzZWN0cyhiYm94LCBub2RlLmJib3gpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZC5iYm94O1xuXG4gICAgICAgICAgICAgICAgaWYgKGludGVyc2VjdHMoYmJveCwgY2hpbGRCQm94KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IGNvbnRhaW5zKGJib3gsIGNoaWxkQkJveCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1RvU2VhcmNoLnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICBsb2FkOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBpZiAoIShkYXRhICYmIGRhdGEubGVuZ3RoKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgdGhpcy5fbWluRW50cmllcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluc2VydChkYXRhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVjdXJzaXZlbHkgYnVpbGQgdGhlIHRyZWUgd2l0aCB0aGUgZ2l2ZW4gZGF0YSBmcm9tIHN0cmF0Y2ggdXNpbmcgT01UIGFsZ29yaXRobVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX2J1aWxkKGRhdGEuc2xpY2UoKSwgMCwgZGF0YS5sZW5ndGggLSAxLCAwKTtcblxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHNhdmUgYXMgaXMgaWYgdHJlZSBpcyBlbXB0eVxuICAgICAgICAgICAgdGhpcy5kYXRhID0gbm9kZTtcblxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPT09IG5vZGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICAvLyBzcGxpdCByb290IGlmIHRyZWVzIGhhdmUgdGhlIHNhbWUgaGVpZ2h0XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLCBub2RlKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPCBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgdHJlZXMgaWYgaW5zZXJ0ZWQgb25lIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgIHZhciB0bXBOb2RlID0gdGhpcy5kYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IHRtcE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGluc2VydCB0aGUgc21hbGwgdHJlZSBpbnRvIHRoZSBsYXJnZSB0cmVlIGF0IGFwcHJvcHJpYXRlIGxldmVsXG4gICAgICAgICAgICB0aGlzLl9pbnNlcnQobm9kZSwgdGhpcy5kYXRhLmhlaWdodCAtIG5vZGUuaGVpZ2h0IC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBpZiAoaXRlbSkgdGhpcy5faW5zZXJ0KGl0ZW0sIHRoaXMuZGF0YS5oZWlnaHQgLSAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgICAgIGJib3g6IGVtcHR5KCksXG4gICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICByZW1vdmU6IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBub2RlLmNoaWxkcmVuLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiBjb250YWlucyhub2RlLmJib3gsIGJib3gpKSB7IC8vIGdvIGRvd25cbiAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bMF07XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50KSB7IC8vIGdvIHJpZ2h0XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBwYXJlbnQuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9IGVsc2Ugbm9kZSA9IG51bGw7IC8vIG5vdGhpbmcgZm91bmRcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICB0b0JCb3g6IGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBpdGVtOyB9LFxuXG4gICAgY29tcGFyZU1pblg6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhWzBdIC0gYlswXTsgfSxcbiAgICBjb21wYXJlTWluWTogZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGFbMV0gLSBiWzFdOyB9LFxuXG4gICAgdG9KU09OOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmRhdGE7IH0sXG5cbiAgICBmcm9tSlNPTjogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hbGw6IGZ1bmN0aW9uIChub2RlLCByZXN1bHQpIHtcbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXTtcbiAgICAgICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgbm9kZS5jaGlsZHJlbik7XG4gICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaC5hcHBseShub2Rlc1RvU2VhcmNoLCBub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgX2J1aWxkOiBmdW5jdGlvbiAoaXRlbXMsIGxlZnQsIHJpZ2h0LCBoZWlnaHQpIHtcblxuICAgICAgICB2YXIgTiA9IHJpZ2h0IC0gbGVmdCArIDEsXG4gICAgICAgICAgICBNID0gdGhpcy5fbWF4RW50cmllcyxcbiAgICAgICAgICAgIG5vZGU7XG5cbiAgICAgICAgaWYgKE4gPD0gTSkge1xuICAgICAgICAgICAgLy8gcmVhY2hlZCBsZWFmIGxldmVsOyByZXR1cm4gbGVhZlxuICAgICAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgICAgICBjaGlsZHJlbjogaXRlbXMuc2xpY2UobGVmdCwgcmlnaHQgKyAxKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgICAgICAgICAgYmJveDogbnVsbCxcbiAgICAgICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgLy8gdGFyZ2V0IGhlaWdodCBvZiB0aGUgYnVsay1sb2FkZWQgdHJlZVxuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGgubG9nKE4pIC8gTWF0aC5sb2coTSkpO1xuXG4gICAgICAgICAgICAvLyB0YXJnZXQgbnVtYmVyIG9mIHJvb3QgZW50cmllcyB0byBtYXhpbWl6ZSBzdG9yYWdlIHV0aWxpemF0aW9uXG4gICAgICAgICAgICBNID0gTWF0aC5jZWlsKE4gLyBNYXRoLnBvdyhNLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPIGVsaW1pbmF0ZSByZWN1cnNpb24/XG5cbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgYmJveDogbnVsbFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNwbGl0IHRoZSBpdGVtcyBpbnRvIE0gbW9zdGx5IHNxdWFyZSB0aWxlc1xuXG4gICAgICAgIHZhciBOMiA9IE1hdGguY2VpbChOIC8gTSksXG4gICAgICAgICAgICBOMSA9IE4yICogTWF0aC5jZWlsKE1hdGguc3FydChNKSksXG4gICAgICAgICAgICBpLCBqLCByaWdodDIsIHJpZ2h0MztcblxuICAgICAgICBtdWx0aVNlbGVjdChpdGVtcywgbGVmdCwgcmlnaHQsIE4xLCB0aGlzLmNvbXBhcmVNaW5YKTtcblxuICAgICAgICBmb3IgKGkgPSBsZWZ0OyBpIDw9IHJpZ2h0OyBpICs9IE4xKSB7XG5cbiAgICAgICAgICAgIHJpZ2h0MiA9IE1hdGgubWluKGkgKyBOMSAtIDEsIHJpZ2h0KTtcblxuICAgICAgICAgICAgbXVsdGlTZWxlY3QoaXRlbXMsIGksIHJpZ2h0MiwgTjIsIHRoaXMuY29tcGFyZU1pblkpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSBpOyBqIDw9IHJpZ2h0MjsgaiArPSBOMikge1xuXG4gICAgICAgICAgICAgICAgcmlnaHQzID0gTWF0aC5taW4oaiArIE4yIC0gMSwgcmlnaHQyKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgZWFjaCBlbnRyeSByZWN1cnNpdmVseVxuICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4ucHVzaCh0aGlzLl9idWlsZChpdGVtcywgaiwgcmlnaHQzLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjYWxjQkJveChub2RlLCB0aGlzLnRvQkJveCk7XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9jaG9vc2VTdWJ0cmVlOiBmdW5jdGlvbiAoYmJveCwgbm9kZSwgbGV2ZWwsIHBhdGgpIHtcblxuICAgICAgICB2YXIgaSwgbGVuLCBjaGlsZCwgdGFyZ2V0Tm9kZSwgYXJlYSwgZW5sYXJnZW1lbnQsIG1pbkFyZWEsIG1pbkVubGFyZ2VtZW50O1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYgfHwgcGF0aC5sZW5ndGggLSAxID09PSBsZXZlbCkgYnJlYWs7XG5cbiAgICAgICAgICAgIG1pbkFyZWEgPSBtaW5FbmxhcmdlbWVudCA9IEluZmluaXR5O1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShjaGlsZC5iYm94KTtcbiAgICAgICAgICAgICAgICBlbmxhcmdlbWVudCA9IGVubGFyZ2VkQXJlYShiYm94LCBjaGlsZC5iYm94KSAtIGFyZWE7XG5cbiAgICAgICAgICAgICAgICAvLyBjaG9vc2UgZW50cnkgd2l0aCB0aGUgbGVhc3QgYXJlYSBlbmxhcmdlbWVudFxuICAgICAgICAgICAgICAgIGlmIChlbmxhcmdlbWVudCA8IG1pbkVubGFyZ2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkVubGFyZ2VtZW50ID0gZW5sYXJnZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVubGFyZ2VtZW50ID09PSBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIG9uZSB3aXRoIHRoZSBzbWFsbGVzdCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSB0YXJnZXROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9pbnNlcnQ6IGZ1bmN0aW9uIChpdGVtLCBsZXZlbCwgaXNOb2RlKSB7XG5cbiAgICAgICAgdmFyIHRvQkJveCA9IHRoaXMudG9CQm94LFxuICAgICAgICAgICAgYmJveCA9IGlzTm9kZSA/IGl0ZW0uYmJveCA6IHRvQkJveChpdGVtKSxcbiAgICAgICAgICAgIGluc2VydFBhdGggPSBbXTtcblxuICAgICAgICAvLyBmaW5kIHRoZSBiZXN0IG5vZGUgZm9yIGFjY29tbW9kYXRpbmcgdGhlIGl0ZW0sIHNhdmluZyBhbGwgbm9kZXMgYWxvbmcgdGhlIHBhdGggdG9vXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fY2hvb3NlU3VidHJlZShiYm94LCB0aGlzLmRhdGEsIGxldmVsLCBpbnNlcnRQYXRoKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGl0ZW0gaW50byB0aGUgbm9kZVxuICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goaXRlbSk7XG4gICAgICAgIGV4dGVuZChub2RlLmJib3gsIGJib3gpO1xuXG4gICAgICAgIC8vIHNwbGl0IG9uIG5vZGUgb3ZlcmZsb3c7IHByb3BhZ2F0ZSB1cHdhcmRzIGlmIG5lY2Vzc2FyeVxuICAgICAgICB3aGlsZSAobGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAgaWYgKGluc2VydFBhdGhbbGV2ZWxdLmNoaWxkcmVuLmxlbmd0aCA+IHRoaXMuX21heEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zcGxpdChpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgICAgICAgICAgICAgbGV2ZWwtLTtcbiAgICAgICAgICAgIH0gZWxzZSBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBiYm94ZXMgYWxvbmcgdGhlIGluc2VydGlvbiBwYXRoXG4gICAgICAgIHRoaXMuX2FkanVzdFBhcmVudEJCb3hlcyhiYm94LCBpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgfSxcblxuICAgIC8vIHNwbGl0IG92ZXJmbG93ZWQgbm9kZSBpbnRvIHR3b1xuICAgIF9zcGxpdDogZnVuY3Rpb24gKGluc2VydFBhdGgsIGxldmVsKSB7XG5cbiAgICAgICAgdmFyIG5vZGUgPSBpbnNlcnRQYXRoW2xldmVsXSxcbiAgICAgICAgICAgIE0gPSBub2RlLmNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICAgIG0gPSB0aGlzLl9taW5FbnRyaWVzO1xuXG4gICAgICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhub2RlLCBtLCBNKTtcblxuICAgICAgICB2YXIgbmV3Tm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLnNwbGljZSh0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pKSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobm9kZS5sZWFmKSBuZXdOb2RlLmxlYWYgPSB0cnVlO1xuXG4gICAgICAgIGNhbGNCQm94KG5vZGUsIHRoaXMudG9CQm94KTtcbiAgICAgICAgY2FsY0JCb3gobmV3Tm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIGlmIChsZXZlbCkgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIGVsc2UgdGhpcy5fc3BsaXRSb290KG5vZGUsIG5ld05vZGUpO1xuICAgIH0sXG5cbiAgICBfc3BsaXRSb290OiBmdW5jdGlvbiAobm9kZSwgbmV3Tm9kZSkge1xuICAgICAgICAvLyBzcGxpdCByb290IG5vZGVcbiAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtub2RlLCBuZXdOb2RlXSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHQgKyAxXG4gICAgICAgIH07XG4gICAgICAgIGNhbGNCQm94KHRoaXMuZGF0YSwgdGhpcy50b0JCb3gpO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3BsaXRJbmRleDogZnVuY3Rpb24gKG5vZGUsIG0sIE0pIHtcblxuICAgICAgICB2YXIgaSwgYmJveDEsIGJib3gyLCBvdmVybGFwLCBhcmVhLCBtaW5PdmVybGFwLCBtaW5BcmVhLCBpbmRleDtcblxuICAgICAgICBtaW5PdmVybGFwID0gbWluQXJlYSA9IEluZmluaXR5O1xuXG4gICAgICAgIGZvciAoaSA9IG07IGkgPD0gTSAtIG07IGkrKykge1xuICAgICAgICAgICAgYmJveDEgPSBkaXN0QkJveChub2RlLCAwLCBpLCB0aGlzLnRvQkJveCk7XG4gICAgICAgICAgICBiYm94MiA9IGRpc3RCQm94KG5vZGUsIGksIE0sIHRoaXMudG9CQm94KTtcblxuICAgICAgICAgICAgb3ZlcmxhcCA9IGludGVyc2VjdGlvbkFyZWEoYmJveDEsIGJib3gyKTtcbiAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShiYm94MSkgKyBiYm94QXJlYShiYm94Mik7XG5cbiAgICAgICAgICAgIC8vIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIG92ZXJsYXBcbiAgICAgICAgICAgIGlmIChvdmVybGFwIDwgbWluT3ZlcmxhcCkge1xuICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSBvdmVybGFwO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcblxuICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG92ZXJsYXAgPT09IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbmltdW0gYXJlYVxuICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICB9LFxuXG4gICAgLy8gc29ydHMgbm9kZSBjaGlsZHJlbiBieSB0aGUgYmVzdCBheGlzIGZvciBzcGxpdFxuICAgIF9jaG9vc2VTcGxpdEF4aXM6IGZ1bmN0aW9uIChub2RlLCBtLCBNKSB7XG5cbiAgICAgICAgdmFyIGNvbXBhcmVNaW5YID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWCA6IGNvbXBhcmVOb2RlTWluWCxcbiAgICAgICAgICAgIGNvbXBhcmVNaW5ZID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWSA6IGNvbXBhcmVOb2RlTWluWSxcbiAgICAgICAgICAgIHhNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5YKSxcbiAgICAgICAgICAgIHlNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5ZKTtcblxuICAgICAgICAvLyBpZiB0b3RhbCBkaXN0cmlidXRpb25zIG1hcmdpbiB2YWx1ZSBpcyBtaW5pbWFsIGZvciB4LCBzb3J0IGJ5IG1pblgsXG4gICAgICAgIC8vIG90aGVyd2lzZSBpdCdzIGFscmVhZHkgc29ydGVkIGJ5IG1pbllcbiAgICAgICAgaWYgKHhNYXJnaW4gPCB5TWFyZ2luKSBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZU1pblgpO1xuICAgIH0sXG5cbiAgICAvLyB0b3RhbCBtYXJnaW4gb2YgYWxsIHBvc3NpYmxlIHNwbGl0IGRpc3RyaWJ1dGlvbnMgd2hlcmUgZWFjaCBub2RlIGlzIGF0IGxlYXN0IG0gZnVsbFxuICAgIF9hbGxEaXN0TWFyZ2luOiBmdW5jdGlvbiAobm9kZSwgbSwgTSwgY29tcGFyZSkge1xuXG4gICAgICAgIG5vZGUuY2hpbGRyZW4uc29ydChjb21wYXJlKTtcblxuICAgICAgICB2YXIgdG9CQm94ID0gdGhpcy50b0JCb3gsXG4gICAgICAgICAgICBsZWZ0QkJveCA9IGRpc3RCQm94KG5vZGUsIDAsIG0sIHRvQkJveCksXG4gICAgICAgICAgICByaWdodEJCb3ggPSBkaXN0QkJveChub2RlLCBNIC0gbSwgTSwgdG9CQm94KSxcbiAgICAgICAgICAgIG1hcmdpbiA9IGJib3hNYXJnaW4obGVmdEJCb3gpICsgYmJveE1hcmdpbihyaWdodEJCb3gpLFxuICAgICAgICAgICAgaSwgY2hpbGQ7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGV4dGVuZChsZWZ0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4obGVmdEJCb3gpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gTSAtIG0gLSAxOyBpID49IG07IGktLSkge1xuICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgZXh0ZW5kKHJpZ2h0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4ocmlnaHRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXJnaW47XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgZXh0ZW5kKHBhdGhbaV0uYmJveCwgYmJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbmRlbnNlOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIHRoZSBwYXRoLCByZW1vdmluZyBlbXB0eSBub2RlcyBhbmQgdXBkYXRpbmcgYmJveGVzXG4gICAgICAgIGZvciAodmFyIGkgPSBwYXRoLmxlbmd0aCAtIDEsIHNpYmxpbmdzOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKHBhdGhbaV0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzID0gcGF0aFtpIC0gMV0uY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzLnNwbGljZShzaWJsaW5ncy5pbmRleE9mKHBhdGhbaV0pLCAxKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBjYWxjQkJveChwYXRoW2ldLCB0aGlzLnRvQkJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2luaXRGb3JtYXQ6IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgLy8gZGF0YSBmb3JtYXQgKG1pblgsIG1pblksIG1heFgsIG1heFkgYWNjZXNzb3JzKVxuXG4gICAgICAgIC8vIHVzZXMgZXZhbC10eXBlIGZ1bmN0aW9uIGNvbXBpbGF0aW9uIGluc3RlYWQgb2YganVzdCBhY2NlcHRpbmcgYSB0b0JCb3ggZnVuY3Rpb25cbiAgICAgICAgLy8gYmVjYXVzZSB0aGUgYWxnb3JpdGhtcyBhcmUgdmVyeSBzZW5zaXRpdmUgdG8gc29ydGluZyBmdW5jdGlvbnMgcGVyZm9ybWFuY2UsXG4gICAgICAgIC8vIHNvIHRoZXkgc2hvdWxkIGJlIGRlYWQgc2ltcGxlIGFuZCB3aXRob3V0IGlubmVyIGNhbGxzXG5cbiAgICAgICAgLy8ganNoaW50IGV2aWw6IHRydWVcblxuICAgICAgICB2YXIgY29tcGFyZUFyciA9IFsncmV0dXJuIGEnLCAnIC0gYicsICc7J107XG5cbiAgICAgICAgdGhpcy5jb21wYXJlTWluWCA9IG5ldyBGdW5jdGlvbignYScsICdiJywgY29tcGFyZUFyci5qb2luKGZvcm1hdFswXSkpO1xuICAgICAgICB0aGlzLmNvbXBhcmVNaW5ZID0gbmV3IEZ1bmN0aW9uKCdhJywgJ2InLCBjb21wYXJlQXJyLmpvaW4oZm9ybWF0WzFdKSk7XG5cbiAgICAgICAgdGhpcy50b0JCb3ggPSBuZXcgRnVuY3Rpb24oJ2EnLCAncmV0dXJuIFthJyArIGZvcm1hdC5qb2luKCcsIGEnKSArICddOycpO1xuICAgIH1cbn07XG5cblxuLy8gY2FsY3VsYXRlIG5vZGUncyBiYm94IGZyb20gYmJveGVzIG9mIGl0cyBjaGlsZHJlblxuZnVuY3Rpb24gY2FsY0JCb3gobm9kZSwgdG9CQm94KSB7XG4gICAgbm9kZS5iYm94ID0gZGlzdEJCb3gobm9kZSwgMCwgbm9kZS5jaGlsZHJlbi5sZW5ndGgsIHRvQkJveCk7XG59XG5cbi8vIG1pbiBib3VuZGluZyByZWN0YW5nbGUgb2Ygbm9kZSBjaGlsZHJlbiBmcm9tIGsgdG8gcC0xXG5mdW5jdGlvbiBkaXN0QkJveChub2RlLCBrLCBwLCB0b0JCb3gpIHtcbiAgICB2YXIgYmJveCA9IGVtcHR5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICBleHRlbmQoYmJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgIH1cblxuICAgIHJldHVybiBiYm94O1xufVxuXG5mdW5jdGlvbiBlbXB0eSgpIHsgcmV0dXJuIFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsgfVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGFbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBhWzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSk7XG4gICAgYVsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pO1xuICAgIGFbM10gPSBNYXRoLm1heChhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5YKGEsIGIpIHsgcmV0dXJuIGEuYmJveFswXSAtIGIuYmJveFswXTsgfVxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5ZKGEsIGIpIHsgcmV0dXJuIGEuYmJveFsxXSAtIGIuYmJveFsxXTsgfVxuXG5mdW5jdGlvbiBiYm94QXJlYShhKSAgIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKiAoYVszXSAtIGFbMV0pOyB9XG5mdW5jdGlvbiBiYm94TWFyZ2luKGEpIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKyAoYVszXSAtIGFbMV0pOyB9XG5cbmZ1bmN0aW9uIGVubGFyZ2VkQXJlYShhLCBiKSB7XG4gICAgcmV0dXJuIChNYXRoLm1heChiWzJdLCBhWzJdKSAtIE1hdGgubWluKGJbMF0sIGFbMF0pKSAqXG4gICAgICAgICAgIChNYXRoLm1heChiWzNdLCBhWzNdKSAtIE1hdGgubWluKGJbMV0sIGFbMV0pKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uQXJlYShhLCBiKSB7XG4gICAgdmFyIG1pblggPSBNYXRoLm1heChhWzBdLCBiWzBdKSxcbiAgICAgICAgbWluWSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pLFxuICAgICAgICBtYXhYID0gTWF0aC5taW4oYVsyXSwgYlsyXSksXG4gICAgICAgIG1heFkgPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcblxuICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICBNYXRoLm1heCgwLCBtYXhZIC0gbWluWSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSA8PSBiWzBdICYmXG4gICAgICAgICAgIGFbMV0gPD0gYlsxXSAmJlxuICAgICAgICAgICBiWzJdIDw9IGFbMl0gJiZcbiAgICAgICAgICAgYlszXSA8PSBhWzNdO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RzKGEsIGIpIHtcbiAgICByZXR1cm4gYlswXSA8PSBhWzJdICYmXG4gICAgICAgICAgIGJbMV0gPD0gYVszXSAmJlxuICAgICAgICAgICBiWzJdID49IGFbMF0gJiZcbiAgICAgICAgICAgYlszXSA+PSBhWzFdO1xufVxuXG4vLyBzb3J0IGFuIGFycmF5IHNvIHRoYXQgaXRlbXMgY29tZSBpbiBncm91cHMgb2YgbiB1bnNvcnRlZCBpdGVtcywgd2l0aCBncm91cHMgc29ydGVkIGJldHdlZW4gZWFjaCBvdGhlcjtcbi8vIGNvbWJpbmVzIHNlbGVjdGlvbiBhbGdvcml0aG0gd2l0aCBiaW5hcnkgZGl2aWRlICYgY29ucXVlciBhcHByb2FjaFxuXG5mdW5jdGlvbiBtdWx0aVNlbGVjdChhcnIsIGxlZnQsIHJpZ2h0LCBuLCBjb21wYXJlKSB7XG4gICAgdmFyIHN0YWNrID0gW2xlZnQsIHJpZ2h0XSxcbiAgICAgICAgbWlkO1xuXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgICAgICByaWdodCA9IHN0YWNrLnBvcCgpO1xuICAgICAgICBsZWZ0ID0gc3RhY2sucG9wKCk7XG5cbiAgICAgICAgaWYgKHJpZ2h0IC0gbGVmdCA8PSBuKSBjb250aW51ZTtcblxuICAgICAgICBtaWQgPSBsZWZ0ICsgTWF0aC5jZWlsKChyaWdodCAtIGxlZnQpIC8gbiAvIDIpICogbjtcbiAgICAgICAgc2VsZWN0KGFyciwgbGVmdCwgcmlnaHQsIG1pZCwgY29tcGFyZSk7XG5cbiAgICAgICAgc3RhY2sucHVzaChsZWZ0LCBtaWQsIG1pZCwgcmlnaHQpO1xuICAgIH1cbn1cblxuLy8gRmxveWQtUml2ZXN0IHNlbGVjdGlvbiBhbGdvcml0aG06XG4vLyBzb3J0IGFuIGFycmF5IGJldHdlZW4gbGVmdCBhbmQgcmlnaHQgKGluY2x1c2l2ZSkgc28gdGhhdCB0aGUgc21hbGxlc3QgayBlbGVtZW50cyBjb21lIGZpcnN0ICh1bm9yZGVyZWQpXG5mdW5jdGlvbiBzZWxlY3QoYXJyLCBsZWZ0LCByaWdodCwgaywgY29tcGFyZSkge1xuICAgIHZhciBuLCBpLCB6LCBzLCBzZCwgbmV3TGVmdCwgbmV3UmlnaHQsIHQsIGo7XG5cbiAgICB3aGlsZSAocmlnaHQgPiBsZWZ0KSB7XG4gICAgICAgIGlmIChyaWdodCAtIGxlZnQgPiA2MDApIHtcbiAgICAgICAgICAgIG4gPSByaWdodCAtIGxlZnQgKyAxO1xuICAgICAgICAgICAgaSA9IGsgLSBsZWZ0ICsgMTtcbiAgICAgICAgICAgIHogPSBNYXRoLmxvZyhuKTtcbiAgICAgICAgICAgIHMgPSAwLjUgKiBNYXRoLmV4cCgyICogeiAvIDMpO1xuICAgICAgICAgICAgc2QgPSAwLjUgKiBNYXRoLnNxcnQoeiAqIHMgKiAobiAtIHMpIC8gbikgKiAoaSAtIG4gLyAyIDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBuZXdMZWZ0ID0gTWF0aC5tYXgobGVmdCwgTWF0aC5mbG9vcihrIC0gaSAqIHMgLyBuICsgc2QpKTtcbiAgICAgICAgICAgIG5ld1JpZ2h0ID0gTWF0aC5taW4ocmlnaHQsIE1hdGguZmxvb3IoayArIChuIC0gaSkgKiBzIC8gbiArIHNkKSk7XG4gICAgICAgICAgICBzZWxlY3QoYXJyLCBuZXdMZWZ0LCBuZXdSaWdodCwgaywgY29tcGFyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0ID0gYXJyW2tdO1xuICAgICAgICBpID0gbGVmdDtcbiAgICAgICAgaiA9IHJpZ2h0O1xuXG4gICAgICAgIHN3YXAoYXJyLCBsZWZ0LCBrKTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYXJyW3JpZ2h0XSwgdCkgPiAwKSBzd2FwKGFyciwgbGVmdCwgcmlnaHQpO1xuXG4gICAgICAgIHdoaWxlIChpIDwgaikge1xuICAgICAgICAgICAgc3dhcChhcnIsIGksIGopO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgd2hpbGUgKGNvbXBhcmUoYXJyW2ldLCB0KSA8IDApIGkrKztcbiAgICAgICAgICAgIHdoaWxlIChjb21wYXJlKGFycltqXSwgdCkgPiAwKSBqLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29tcGFyZShhcnJbbGVmdF0sIHQpID09PSAwKSBzd2FwKGFyciwgbGVmdCwgaik7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgc3dhcChhcnIsIGosIHJpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqIDw9IGspIGxlZnQgPSBqICsgMTtcbiAgICAgICAgaWYgKGsgPD0gaikgcmlnaHQgPSBqIC0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoYXJyLCBpLCBqKSB7XG4gICAgdmFyIHRtcCA9IGFycltpXTtcbiAgICBhcnJbaV0gPSBhcnJbal07XG4gICAgYXJyW2pdID0gdG1wO1xufVxuXG5cbi8vIGV4cG9ydCBhcyBBTUQvQ29tbW9uSlMgbW9kdWxlIG9yIGdsb2JhbCB2YXJpYWJsZVxuaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgZGVmaW5lKCdyYnVzaCcsIGZ1bmN0aW9uKCkgeyByZXR1cm4gcmJ1c2g7IH0pO1xuZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpIG1vZHVsZS5leHBvcnRzID0gcmJ1c2g7XG5lbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHNlbGYucmJ1c2ggPSByYnVzaDtcbmVsc2Ugd2luZG93LnJidXNoID0gcmJ1c2g7XG5cbn0pKCk7XG4iLCIvLyBDb3B5cmlnaHQgMjAxNCBTaW1vbiBMeWRlbGxcclxuLy8gWDExICjigJxNSVTigJ0pIExpY2Vuc2VkLiAoU2VlIExJQ0VOU0UuKVxyXG5cclxudm9pZCAoZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkge1xyXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xyXG4gICAgZGVmaW5lKGZhY3RvcnkpXHJcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KClcclxuICB9IGVsc2Uge1xyXG4gICAgcm9vdC5yZXNvbHZlVXJsID0gZmFjdG9yeSgpXHJcbiAgfVxyXG59KHRoaXMsIGZ1bmN0aW9uKCkge1xyXG5cclxuICBmdW5jdGlvbiByZXNvbHZlVXJsKC8qIC4uLnVybHMgKi8pIHtcclxuICAgIHZhciBudW1VcmxzID0gYXJndW1lbnRzLmxlbmd0aFxyXG5cclxuICAgIGlmIChudW1VcmxzID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInJlc29sdmVVcmwgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50OyBnb3Qgbm9uZS5cIilcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYmFzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiYXNlXCIpXHJcbiAgICBiYXNlLmhyZWYgPSBhcmd1bWVudHNbMF1cclxuXHJcbiAgICBpZiAobnVtVXJscyA9PT0gMSkge1xyXG4gICAgICByZXR1cm4gYmFzZS5ocmVmXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImhlYWRcIilbMF1cclxuICAgIGhlYWQuaW5zZXJ0QmVmb3JlKGJhc2UsIGhlYWQuZmlyc3RDaGlsZClcclxuXHJcbiAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpXHJcbiAgICB2YXIgcmVzb2x2ZWRcclxuXHJcbiAgICBmb3IgKHZhciBpbmRleCA9IDE7IGluZGV4IDwgbnVtVXJsczsgaW5kZXgrKykge1xyXG4gICAgICBhLmhyZWYgPSBhcmd1bWVudHNbaW5kZXhdXHJcbiAgICAgIHJlc29sdmVkID0gYS5ocmVmXHJcbiAgICAgIGJhc2UuaHJlZiA9IHJlc29sdmVkXHJcbiAgICB9XHJcblxyXG4gICAgaGVhZC5yZW1vdmVDaGlsZChiYXNlKVxyXG5cclxuICAgIHJldHVybiByZXNvbHZlZFxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc29sdmVVcmxcclxuXHJcbn0pKTtcclxuIiwiLypcbiAqIENvcHlyaWdodCAoQykgMjAwOCBBcHBsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnNcbiAqIGFyZSBtZXQ6XG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodFxuICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGVcbiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIGBgQVMgSVMnJyBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuICogSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSXG4gKiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgQVBQTEUgSU5DLiBPUlxuICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sXG4gKiBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1JcbiAqIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gKiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICpcbiAqIFBvcnRlZCBmcm9tIFdlYmtpdFxuICogaHR0cDovL3N2bi53ZWJraXQub3JnL3JlcG9zaXRvcnkvd2Via2l0L3RydW5rL1NvdXJjZS9XZWJDb3JlL3BsYXRmb3JtL2dyYXBoaWNzL1VuaXRCZXppZXIuaFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gVW5pdEJlemllcjtcblxuZnVuY3Rpb24gVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpIHtcbiAgICAvLyBDYWxjdWxhdGUgdGhlIHBvbHlub21pYWwgY29lZmZpY2llbnRzLCBpbXBsaWNpdCBmaXJzdCBhbmQgbGFzdCBjb250cm9sIHBvaW50cyBhcmUgKDAsMCkgYW5kICgxLDEpLlxuICAgIHRoaXMuY3ggPSAzLjAgKiBwMXg7XG4gICAgdGhpcy5ieCA9IDMuMCAqIChwMnggLSBwMXgpIC0gdGhpcy5jeDtcbiAgICB0aGlzLmF4ID0gMS4wIC0gdGhpcy5jeCAtIHRoaXMuYng7XG5cbiAgICB0aGlzLmN5ID0gMy4wICogcDF5O1xuICAgIHRoaXMuYnkgPSAzLjAgKiAocDJ5IC0gcDF5KSAtIHRoaXMuY3k7XG4gICAgdGhpcy5heSA9IDEuMCAtIHRoaXMuY3kgLSB0aGlzLmJ5O1xuXG4gICAgdGhpcy5wMXggPSBwMXg7XG4gICAgdGhpcy5wMXkgPSBwMnk7XG4gICAgdGhpcy5wMnggPSBwMng7XG4gICAgdGhpcy5wMnkgPSBwMnk7XG59XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWCA9IGZ1bmN0aW9uKHQpIHtcbiAgICAvLyBgYXggdF4zICsgYnggdF4yICsgY3ggdCcgZXhwYW5kZWQgdXNpbmcgSG9ybmVyJ3MgcnVsZS5cbiAgICByZXR1cm4gKCh0aGlzLmF4ICogdCArIHRoaXMuYngpICogdCArIHRoaXMuY3gpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWSA9IGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gKCh0aGlzLmF5ICogdCArIHRoaXMuYnkpICogdCArIHRoaXMuY3kpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVggPSBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuICgzLjAgKiB0aGlzLmF4ICogdCArIDIuMCAqIHRoaXMuYngpICogdCArIHRoaXMuY3g7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zb2x2ZUN1cnZlWCA9IGZ1bmN0aW9uKHgsIGVwc2lsb24pIHtcbiAgICBpZiAodHlwZW9mIGVwc2lsb24gPT09ICd1bmRlZmluZWQnKSBlcHNpbG9uID0gMWUtNjtcblxuICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgaTtcblxuICAgIC8vIEZpcnN0IHRyeSBhIGZldyBpdGVyYXRpb25zIG9mIE5ld3RvbidzIG1ldGhvZCAtLSBub3JtYWxseSB2ZXJ5IGZhc3QuXG4gICAgZm9yICh0MiA9IHgsIGkgPSAwOyBpIDwgODsgaSsrKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0MikgLSB4O1xuICAgICAgICBpZiAoTWF0aC5hYnMoeDIpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIHZhciBkMiA9IHRoaXMuc2FtcGxlQ3VydmVEZXJpdmF0aXZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyhkMikgPCAxZS02KSBicmVhaztcblxuICAgICAgICB0MiA9IHQyIC0geDIgLyBkMjtcbiAgICB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gdGhlIGJpc2VjdGlvbiBtZXRob2QgZm9yIHJlbGlhYmlsaXR5LlxuICAgIHQwID0gMC4wO1xuICAgIHQxID0gMS4wO1xuICAgIHQyID0geDtcblxuICAgIGlmICh0MiA8IHQwKSByZXR1cm4gdDA7XG4gICAgaWYgKHQyID4gdDEpIHJldHVybiB0MTtcblxuICAgIHdoaWxlICh0MCA8IHQxKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyh4MiAtIHgpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIGlmICh4ID4geDIpIHtcbiAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0MSA9IHQyO1xuICAgICAgICB9XG5cbiAgICAgICAgdDIgPSAodDEgLSB0MCkgKiAwLjUgKyB0MDtcbiAgICB9XG5cbiAgICAvLyBGYWlsdXJlLlxuICAgIHJldHVybiB0Mjtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNvbHZlID0gZnVuY3Rpb24oeCwgZXBzaWxvbikge1xuICAgIHJldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHgsIGVwc2lsb24pKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cy5WZWN0b3JUaWxlID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCcuL2xpYi92ZWN0b3J0aWxlZmVhdHVyZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUxheWVyID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZWxheWVyLmpzJyk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlTGF5ZXIgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGVsYXllcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZlY3RvclRpbGU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGUocGJmLCBlbmQpIHtcbiAgICB0aGlzLmxheWVycyA9IHBiZi5yZWFkRmllbGRzKHJlYWRUaWxlLCB7fSwgZW5kKTtcbn1cblxuZnVuY3Rpb24gcmVhZFRpbGUodGFnLCBsYXllcnMsIHBiZikge1xuICAgIGlmICh0YWcgPT09IDMpIHtcbiAgICAgICAgdmFyIGxheWVyID0gbmV3IFZlY3RvclRpbGVMYXllcihwYmYsIHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zKTtcbiAgICAgICAgaWYgKGxheWVyLmxlbmd0aCkgbGF5ZXJzW2xheWVyLm5hbWVdID0gbGF5ZXI7XG4gICAgfVxufVxuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmVjdG9yVGlsZUZlYXR1cmU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVGZWF0dXJlKHBiZiwgZW5kLCBleHRlbnQsIGtleXMsIHZhbHVlcykge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMucHJvcGVydGllcyA9IHt9O1xuICAgIHRoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIHRoaXMudHlwZSA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fcGJmID0gcGJmO1xuICAgIHRoaXMuX2dlb21ldHJ5ID0gLTE7XG4gICAgdGhpcy5fa2V5cyA9IGtleXM7XG4gICAgdGhpcy5fdmFsdWVzID0gdmFsdWVzO1xuXG4gICAgcGJmLnJlYWRGaWVsZHMocmVhZEZlYXR1cmUsIHRoaXMsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRGZWF0dXJlKHRhZywgZmVhdHVyZSwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PSAxKSBmZWF0dXJlLl9pZCA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgZWxzZSBpZiAodGFnID09IDIpIHJlYWRUYWcocGJmLCBmZWF0dXJlKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gMykgZmVhdHVyZS50eXBlID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gNCkgZmVhdHVyZS5fZ2VvbWV0cnkgPSBwYmYucG9zO1xufVxuXG5mdW5jdGlvbiByZWFkVGFnKHBiZiwgZmVhdHVyZSkge1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhciBrZXkgPSBmZWF0dXJlLl9rZXlzW3BiZi5yZWFkVmFyaW50KCldLFxuICAgICAgICAgICAgdmFsdWUgPSBmZWF0dXJlLl92YWx1ZXNbcGJmLnJlYWRWYXJpbnQoKV07XG4gICAgICAgIGZlYXR1cmUucHJvcGVydGllc1trZXldID0gdmFsdWU7XG4gICAgfVxufVxuXG5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyA9IFsnVW5rbm93bicsICdQb2ludCcsICdMaW5lU3RyaW5nJywgJ1BvbHlnb24nXTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIGxpbmVzID0gW10sXG4gICAgICAgIGxpbmU7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGNtZExlbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgICAgICAgICBjbWQgPSBjbWRMZW4gJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRMZW4gPj4gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGxlbmd0aC0tO1xuXG4gICAgICAgIGlmIChjbWQgPT09IDEgfHwgY21kID09PSAyKSB7XG4gICAgICAgICAgICB4ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgeSArPSBwYmYucmVhZFNWYXJpbnQoKTtcblxuICAgICAgICAgICAgaWYgKGNtZCA9PT0gMSkgeyAvLyBtb3ZlVG9cbiAgICAgICAgICAgICAgICBpZiAobGluZSkgbGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUucHVzaChuZXcgUG9pbnQoeCwgeSkpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kID09PSA3KSB7XG4gICAgICAgICAgICBsaW5lLnB1c2gobGluZVswXS5jbG9uZSgpKTsgLy8gY2xvc2VQb2x5Z29uXG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxpbmUpIGxpbmVzLnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gbGluZXM7XG59O1xuXG5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgY21kTGVuID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZExlbiAmIDB4NztcbiAgICAgICAgICAgIGxlbmd0aCA9IGNtZExlbiA+PiAzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVuZ3RoLS07XG5cbiAgICAgICAgaWYgKGNtZCA9PT0gMSB8fCBjbWQgPT09IDIpIHtcbiAgICAgICAgICAgIHggKz0gcGJmLnJlYWRTVmFyaW50KCk7XG4gICAgICAgICAgICB5ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgaWYgKHggPCB4MSkgeDEgPSB4O1xuICAgICAgICAgICAgaWYgKHggPiB4MikgeDIgPSB4O1xuICAgICAgICAgICAgaWYgKHkgPCB5MSkgeTEgPSB5O1xuICAgICAgICAgICAgaWYgKHkgPiB5MikgeTIgPSB5O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kICE9PSA3KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vua25vd24gY29tbWFuZCAnICsgY21kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbeDEsIHkxLCB4MiwgeTJdO1xufTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZXh0ZW50ICogTWF0aC5wb3coMiwgeiksXG4gICAgICAgIHgwID0gdGhpcy5leHRlbnQgKiB4LFxuICAgICAgICB5MCA9IHRoaXMuZXh0ZW50ICogeSxcbiAgICAgICAgY29vcmRzID0gdGhpcy5sb2FkR2VvbWV0cnkoKSxcbiAgICAgICAgdHlwZSA9IFZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW3RoaXMudHlwZV07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGNvb3Jkc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsaW5lLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGxpbmVbal0sIHkyID0gMTgwIC0gKHAueSArIHkwKSAqIDM2MCAvIHNpemU7XG4gICAgICAgICAgICBsaW5lW2pdID0gW1xuICAgICAgICAgICAgICAgIChwLnggKyB4MCkgKiAzNjAgLyBzaXplIC0gMTgwLFxuICAgICAgICAgICAgICAgIDM2MCAvIE1hdGguUEkgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIgKiBNYXRoLlBJIC8gMTgwKSkgLSA5MFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnUG9pbnQnICYmIGNvb3Jkcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY29vcmRzID0gY29vcmRzWzBdWzBdO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgICAgIHR5cGUgPSAnTXVsdGlQb2ludCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycgJiYgY29vcmRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycpIHtcbiAgICAgICAgdHlwZSA9ICdNdWx0aUxpbmVTdHJpbmcnO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHNcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZSA9IHJlcXVpcmUoJy4vdmVjdG9ydGlsZWZlYXR1cmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVMYXllcihwYmYsIGVuZCkge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMudmVyc2lvbiA9IDE7XG4gICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICB0aGlzLmV4dGVudCA9IDQwOTY7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuXG4gICAgLy8gUHJpdmF0ZVxuICAgIHRoaXMuX3BiZiA9IHBiZjtcbiAgICB0aGlzLl9rZXlzID0gW107XG4gICAgdGhpcy5fdmFsdWVzID0gW107XG4gICAgdGhpcy5fZmVhdHVyZXMgPSBbXTtcblxuICAgIHBiZi5yZWFkRmllbGRzKHJlYWRMYXllciwgdGhpcywgZW5kKTtcblxuICAgIHRoaXMubGVuZ3RoID0gdGhpcy5fZmVhdHVyZXMubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiByZWFkTGF5ZXIodGFnLCBsYXllciwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMTUpIGxheWVyLnZlcnNpb24gPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMSkgbGF5ZXIubmFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSA1KSBsYXllci5leHRlbnQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgbGF5ZXIuX2ZlYXR1cmVzLnB1c2gocGJmLnBvcyk7XG4gICAgZWxzZSBpZiAodGFnID09PSAzKSBsYXllci5fa2V5cy5wdXNoKHBiZi5yZWFkU3RyaW5nKCkpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgbGF5ZXIuX3ZhbHVlcy5wdXNoKHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSB7XG4gICAgdmFyIHZhbHVlID0gbnVsbCxcbiAgICAgICAgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICB2YXIgdGFnID0gcGJmLnJlYWRWYXJpbnQoKSA+PiAzO1xuXG4gICAgICAgIHZhbHVlID0gdGFnID09PSAxID8gcGJmLnJlYWRTdHJpbmcoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDIgPyBwYmYucmVhZEZsb2F0KCkgOlxuICAgICAgICAgICAgdGFnID09PSAzID8gcGJmLnJlYWREb3VibGUoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDQgPyBwYmYucmVhZFZhcmludDY0KCkgOlxuICAgICAgICAgICAgdGFnID09PSA1ID8gcGJmLnJlYWRWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDYgPyBwYmYucmVhZFNWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDcgPyBwYmYucmVhZEJvb2xlYW4oKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufVxuXG4vLyByZXR1cm4gZmVhdHVyZSBgaWAgZnJvbSB0aGlzIGxheWVyIGFzIGEgYFZlY3RvclRpbGVGZWF0dXJlYFxuVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5mZWF0dXJlID0gZnVuY3Rpb24oaSkge1xuICAgIGlmIChpIDwgMCB8fCBpID49IHRoaXMuX2ZlYXR1cmVzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHMnKTtcblxuICAgIHRoaXMuX3BiZi5wb3MgPSB0aGlzLl9mZWF0dXJlc1tpXTtcblxuICAgIHZhciBlbmQgPSB0aGlzLl9wYmYucmVhZFZhcmludCgpICsgdGhpcy5fcGJmLnBvcztcbiAgICByZXR1cm4gbmV3IFZlY3RvclRpbGVGZWF0dXJlKHRoaXMuX3BiZiwgZW5kLCB0aGlzLmV4dGVudCwgdGhpcy5fa2V5cywgdGhpcy5fdmFsdWVzKTtcbn07XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsInZhciBidW5kbGVGbiA9IGFyZ3VtZW50c1szXTtcbnZhciBzb3VyY2VzID0gYXJndW1lbnRzWzRdO1xudmFyIGNhY2hlID0gYXJndW1lbnRzWzVdO1xuXG52YXIgc3RyaW5naWZ5ID0gSlNPTi5zdHJpbmdpZnk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICB2YXIgd2tleTtcbiAgICB2YXIgY2FjaGVLZXlzID0gT2JqZWN0LmtleXMoY2FjaGUpO1xuICAgIFxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2FjaGVLZXlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICBpZiAoY2FjaGVba2V5XS5leHBvcnRzID09PSBmbikge1xuICAgICAgICAgICAgd2tleSA9IGtleTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlmICghd2tleSkge1xuICAgICAgICB3a2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgICAgIHZhciB3Y2FjaGUgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjYWNoZUtleXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICAgICAgd2NhY2hlW2tleV0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgICAgc291cmNlc1t3a2V5XSA9IFtcbiAgICAgICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZScsJ21vZHVsZScsJ2V4cG9ydHMnXSwgJygnICsgZm4gKyAnKShzZWxmKScpLFxuICAgICAgICAgICAgd2NhY2hlXG4gICAgICAgIF07XG4gICAgfVxuICAgIHZhciBza2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgXG4gICAgdmFyIHNjYWNoZSA9IHt9OyBzY2FjaGVbd2tleV0gPSB3a2V5O1xuICAgIHNvdXJjZXNbc2tleV0gPSBbXG4gICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZSddLCdyZXF1aXJlKCcgKyBzdHJpbmdpZnkod2tleSkgKyAnKShzZWxmKScpLFxuICAgICAgICBzY2FjaGVcbiAgICBdO1xuICAgIFxuICAgIHZhciBzcmMgPSAnKCcgKyBidW5kbGVGbiArICcpKHsnXG4gICAgICAgICsgT2JqZWN0LmtleXMoc291cmNlcykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdpZnkoa2V5KSArICc6WydcbiAgICAgICAgICAgICAgICArIHNvdXJjZXNba2V5XVswXVxuICAgICAgICAgICAgICAgICsgJywnICsgc3RyaW5naWZ5KHNvdXJjZXNba2V5XVsxXSkgKyAnXSdcbiAgICAgICAgICAgIDtcbiAgICAgICAgfSkuam9pbignLCcpXG4gICAgICAgICsgJ30se30sWycgKyBzdHJpbmdpZnkoc2tleSkgKyAnXSknXG4gICAgO1xuICAgIFxuICAgIHZhciBVUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkwgfHwgd2luZG93Lm1velVSTCB8fCB3aW5kb3cubXNVUkw7XG4gICAgXG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoVVJMLmNyZWF0ZU9iamVjdFVSTChcbiAgICAgICAgbmV3IEJsb2IoW3NyY10sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSlcbiAgICApKTtcbn07XG4iXX0=
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.mapboxgl = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
// a simple wrapper around a single arraybuffer
module.exports = Buffer;
function Buffer(buffer) {
if (!buffer) {
this.array = new ArrayBuffer(this.defaultLength);
this.length = this.defaultLength;
this.setupViews();
} else {
// we only recreate buffers after receiving them from workers for binding to gl,
// so we only need these 2 properties
this.array = buffer.array;
this.pos = buffer.pos;
}
}
Buffer.prototype = {
pos: 0,
itemSize: 4, // bytes in one item
defaultLength: 8192, // initial buffer size
arrayType: 'ARRAY_BUFFER', // gl buffer type
get index() {
return this.pos / this.itemSize;
},
setupViews: function() {
// set up views for each type to add data of different types to the same buffer
this.ubytes = new Uint8Array(this.array);
this.bytes = new Int8Array(this.array);
this.ushorts = new Uint16Array(this.array);
this.shorts = new Int16Array(this.array);
},
// binds the buffer to a webgl context
bind: function(gl) {
var type = gl[this.arrayType];
if (!this.buffer) {
this.buffer = gl.createBuffer();
gl.bindBuffer(type, this.buffer);
gl.bufferData(type, this.array.slice(0, this.pos), gl.STATIC_DRAW);
// dump array buffer once it's bound to gl
this.array = null;
} else {
gl.bindBuffer(type, this.buffer);
}
},
destroy: function(gl) {
if (this.buffer) {
gl.deleteBuffer(this.buffer);
}
},
// increase the buffer size by 50% if a new item doesn't fit
resize: function() {
if (this.length < this.pos + this.itemSize) {
while (this.length < this.pos + this.itemSize) {
// increase the length by 50% but keep it even
this.length = Math.round(this.length * 1.5 / 2) * 2;
}
// array buffers can't be resized, so we create a new one and reset all bytes there
this.array = new ArrayBuffer(this.length);
var ubytes = new Uint8Array(this.array);
ubytes.set(this.ubytes);
this.setupViews();
}
}
};
},{}],2:[function(require,module,exports){
'use strict';
var LineVertexBuffer = require('./line_vertex_buffer');
var LineElementBuffer = require('./line_element_buffer');
var FillVertexBuffer = require('./fill_vertex_buffer');
var FillElementBuffer = require('./triangle_element_buffer');
var OutlineElementBuffer = require('./outline_elements_buffer');
var GlyphVertexBuffer = require('./glyph_vertex_buffer');
var GlyphElementBuffer = require('./triangle_element_buffer');
var IconVertexBuffer = require('./icon_vertex_buffer');
var IconElementBuffer = require('./triangle_element_buffer');
var CollisionBoxVertexBuffer = require('./collision_box_vertex_buffer');
module.exports = function(bufferset) {
bufferset = bufferset || {};
return {
glyphVertex: new GlyphVertexBuffer(bufferset.glyphVertex),
glyphElement: new GlyphElementBuffer(bufferset.glyphElement),
iconVertex: new IconVertexBuffer(bufferset.iconVertex),
iconElement: new IconElementBuffer(bufferset.iconElement),
fillVertex: new FillVertexBuffer(bufferset.fillVertex),
fillElement: new FillElementBuffer(bufferset.fillElement),
outlineElement: new OutlineElementBuffer(bufferset.outlineElement),
lineVertex: new LineVertexBuffer(bufferset.lineVertex),
lineElement: new LineElementBuffer(bufferset.lineElement),
collisionBoxVertex: new CollisionBoxVertexBuffer(bufferset.collisionBoxVertex)
};
};
},{"./collision_box_vertex_buffer":3,"./fill_vertex_buffer":4,"./glyph_vertex_buffer":5,"./icon_vertex_buffer":6,"./line_element_buffer":7,"./line_vertex_buffer":8,"./outline_elements_buffer":9,"./triangle_element_buffer":10}],3:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = CollisionBoxVertexBuffer;
function CollisionBoxVertexBuffer(buffer) {
Buffer.call(this, buffer);
}
CollisionBoxVertexBuffer.prototype = util.inherit(Buffer, {
itemSize: 12, // bytes per vertex (2 * short + 1 * short + 2 * byte = 8 bytes)
defaultLength: 32768,
// add a vertex to this buffer;
// x, y - vertex position
// ex, ey - extrude normal
add: function(point, extrude, maxZoom, placementZoom) {
var pos = this.pos,
pos2 = pos / 2,
index = this.index;
this.resize();
this.shorts[pos2 + 0] = point.x;
this.shorts[pos2 + 1] = point.y;
this.shorts[pos2 + 2] = Math.round(extrude.x);
this.shorts[pos2 + 3] = Math.round(extrude.y);
this.ubytes[pos + 8] = Math.floor(maxZoom * 10);
this.ubytes[pos + 9] = Math.floor(placementZoom * 10);
this.pos += this.itemSize;
return index;
}
});
},{"../../util/util":96,"./buffer":1}],4:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = FillVertexBuffer;
function FillVertexBuffer(buffer) {
Buffer.call(this, buffer);
}
FillVertexBuffer.prototype = util.inherit(Buffer, {
itemSize: 4, // bytes per vertex (2 * short == 4 bytes)
add: function(x, y) {
var pos2 = this.pos / 2;
this.resize();
this.shorts[pos2 + 0] = x;
this.shorts[pos2 + 1] = y;
this.pos += this.itemSize;
}
});
},{"../../util/util":96,"./buffer":1}],5:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = GlyphVertexBuffer;
function GlyphVertexBuffer(buffer) {
Buffer.call(this, buffer);
}
GlyphVertexBuffer.prototype = util.inherit(Buffer, {
defaultLength: 2048 * 16,
itemSize: 16,
add: function(x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom) {
var pos = this.pos,
pos2 = pos / 2;
this.resize();
this.shorts[pos2 + 0] = x;
this.shorts[pos2 + 1] = y;
this.shorts[pos2 + 2] = Math.round(ox * 64); // use 1/64 pixels for placement
this.shorts[pos2 + 3] = Math.round(oy * 64);
// a_data1
this.ubytes[pos + 8] /* tex */ = Math.floor(tx / 4);
this.ubytes[pos + 9] /* tex */ = Math.floor(ty / 4);
this.ubytes[pos + 10] /* labelminzoom */ = Math.floor((labelminzoom) * 10);
// a_data2
this.ubytes[pos + 12] /* minzoom */ = Math.floor((minzoom) * 10); // 1/10 zoom levels: z16 == 160.
this.ubytes[pos + 13] /* maxzoom */ = Math.floor(Math.min(maxzoom, 25) * 10); // 1/10 zoom levels: z16 == 160.
this.pos += this.itemSize;
},
bind: function(gl, shader, offset) {
Buffer.prototype.bind.call(this, gl);
var stride = this.itemSize;
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, offset + 0);
gl.vertexAttribPointer(shader.a_offset, 2, gl.SHORT, false, stride, offset + 4);
gl.vertexAttribPointer(shader.a_data1, 4, gl.UNSIGNED_BYTE, false, stride, offset + 8);
gl.vertexAttribPointer(shader.a_data2, 2, gl.UNSIGNED_BYTE, false, stride, offset + 12);
}
});
},{"../../util/util":96,"./buffer":1}],6:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = GlyphVertexBuffer;
function GlyphVertexBuffer(buffer) {
Buffer.call(this, buffer);
}
GlyphVertexBuffer.prototype = util.inherit(Buffer, {
defaultLength: 2048 * 16,
itemSize: 16,
add: function(x, y, ox, oy, tx, ty, minzoom, maxzoom, labelminzoom) {
var pos = this.pos,
pos2 = pos / 2;
this.resize();
this.shorts[pos2 + 0] = x;
this.shorts[pos2 + 1] = y;
this.shorts[pos2 + 2] = Math.round(ox * 64); // use 1/64 pixels for placement
this.shorts[pos2 + 3] = Math.round(oy * 64);
// a_data1
this.ubytes[pos + 8] /* tex */ = tx / 4;
this.ubytes[pos + 9] /* tex */ = ty / 4;
this.ubytes[pos + 10] /* labelminzoom */ = Math.floor((labelminzoom || 0) * 10);
// a_data2
this.ubytes[pos + 12] /* minzoom */ = Math.floor((minzoom || 0) * 10); // 1/10 zoom levels: z16 == 160.
this.ubytes[pos + 13] /* maxzoom */ = Math.floor(Math.min(maxzoom || 25, 25) * 10); // 1/10 zoom levels: z16 == 160.
this.pos += this.itemSize;
},
bind: function(gl, shader, offset) {
Buffer.prototype.bind.call(this, gl);
var stride = this.itemSize;
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, offset + 0);
gl.vertexAttribPointer(shader.a_offset, 2, gl.SHORT, false, stride, offset + 4);
gl.vertexAttribPointer(shader.a_data1, 4, gl.UNSIGNED_BYTE, false, stride, offset + 8);
gl.vertexAttribPointer(shader.a_data2, 2, gl.UNSIGNED_BYTE, false, stride, offset + 12);
}
});
},{"../../util/util":96,"./buffer":1}],7:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = LineElementBuffer;
function LineElementBuffer(buffer) {
Buffer.call(this, buffer);
}
LineElementBuffer.prototype = util.inherit(Buffer, {
itemSize: 6, // bytes per triangle (3 * unsigned short == 6 bytes)
arrayType: 'ELEMENT_ARRAY_BUFFER',
add: function(a, b, c) {
var pos2 = this.pos / 2;
this.resize();
this.ushorts[pos2 + 0] = a;
this.ushorts[pos2 + 1] = b;
this.ushorts[pos2 + 2] = c;
this.pos += this.itemSize;
}
});
},{"../../util/util":96,"./buffer":1}],8:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = LineVertexBuffer;
function LineVertexBuffer(buffer) {
Buffer.call(this, buffer);
}
// scale the extrusion vector so that the normal length is this value.
// contains the "texture" normals (-1..1). this is distinct from the extrude
// normals for line joins, because the x-value remains 0 for the texture
// normal array, while the extrude normal actually moves the vertex to create
// the acute/bevelled line join.
LineVertexBuffer.extrudeScale = 63;
LineVertexBuffer.prototype = util.inherit(Buffer, {
itemSize: 8, // bytes per vertex (2 * short + 1 * short + 2 * byte = 8 bytes)
defaultLength: 32768,
// add a vertex to this buffer;
// x, y - vertex position
// ex, ey - extrude normal
// tx, ty - texture normal
add: function(point, extrude, tx, ty, linesofar) {
var pos = this.pos,
pos2 = pos / 2,
index = this.index,
extrudeScale = LineVertexBuffer.extrudeScale;
this.resize();
this.shorts[pos2 + 0] = (Math.floor(point.x) * 2) | tx;
this.shorts[pos2 + 1] = (Math.floor(point.y) * 2) | ty;
this.bytes[pos + 4] = Math.round(extrudeScale * extrude.x);
this.bytes[pos + 5] = Math.round(extrudeScale * extrude.y);
this.bytes[pos + 6] = (linesofar || 0) / 128;
this.bytes[pos + 7] = (linesofar || 0) % 128;
this.pos += this.itemSize;
return index;
}
});
},{"../../util/util":96,"./buffer":1}],9:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = OutlineElementsBuffer;
function OutlineElementsBuffer(buffer) {
Buffer.call(this, buffer);
}
OutlineElementsBuffer.prototype = util.inherit(Buffer, {
itemSize: 4, // bytes per line (2 * unsigned short == 4 bytes)
arrayType: 'ELEMENT_ARRAY_BUFFER',
add: function(a, b) {
var pos2 = this.pos / 2;
this.resize();
this.ushorts[pos2 + 0] = a;
this.ushorts[pos2 + 1] = b;
this.pos += this.itemSize;
}
});
},{"../../util/util":96,"./buffer":1}],10:[function(require,module,exports){
'use strict';
var util = require('../../util/util');
var Buffer = require('./buffer');
module.exports = TriangleElementsBuffer;
function TriangleElementsBuffer(buffer) {
Buffer.call(this, buffer);
}
TriangleElementsBuffer.prototype = util.inherit(Buffer, {
itemSize: 6, // bytes per triangle (3 * unsigned short == 6 bytes)
arrayType: 'ELEMENT_ARRAY_BUFFER',
add: function(a, b, c) {
var pos2 = this.pos / 2;
this.resize();
this.ushorts[pos2 + 0] = a;
this.ushorts[pos2 + 1] = b;
this.ushorts[pos2 + 2] = c;
this.pos += this.itemSize;
}
});
},{"../../util/util":96,"./buffer":1}],11:[function(require,module,exports){
'use strict';
module.exports = createBucket;
var LineBucket = require('./line_bucket');
var FillBucket = require('./fill_bucket');
var SymbolBucket = require('./symbol_bucket');
var LayoutProperties = require('../style/layout_properties');
var featureFilter = require('feature-filter');
var StyleDeclarationSet = require('../style/style_declaration_set');
function createBucket(layer, buffers, collision, z, overscaling, collisionDebug) {
var values = new StyleDeclarationSet('layout', layer.type, layer.layout, {}).values(),
fakeZoomHistory = { lastIntegerZoom: Infinity, lastIntegerZoomTime: 0, lastZoom: 0 },
layout = {};
for (var k in values) {
layout[k] = values[k].calculate(z, fakeZoomHistory);
}
var BucketClass =
layer.type === 'line' ? LineBucket :
layer.type === 'fill' ? FillBucket :
layer.type === 'symbol' ? SymbolBucket : null;
var bucket = new BucketClass(buffers, new LayoutProperties[layer.type](layout), collision, overscaling, collisionDebug);
bucket.id = layer.id;
bucket.type = layer.type;
bucket['source-layer'] = layer['source-layer'];
bucket.interactive = layer.interactive;
bucket.minZoom = layer.minzoom;
bucket.maxZoom = layer.maxzoom;
bucket.filter = featureFilter(layer.filter);
bucket.features = [];
return bucket;
}
},{"../style/layout_properties":49,"../style/style_declaration_set":55,"./fill_bucket":14,"./line_bucket":15,"./symbol_bucket":16,"feature-filter":98}],12:[function(require,module,exports){
'use strict';
module.exports = ElementGroups;
function ElementGroups(vertexBuffer, elementBuffer, secondElementBuffer) {
this.vertexBuffer = vertexBuffer;
this.elementBuffer = elementBuffer;
this.secondElementBuffer = secondElementBuffer;
this.groups = [];
}
ElementGroups.prototype.makeRoomFor = function(numVertices) {
if (!this.current || this.current.vertexLength + numVertices > 65535) {
this.current = new ElementGroup(this.vertexBuffer.index,
this.elementBuffer && this.elementBuffer.index,
this.secondElementBuffer && this.secondElementBuffer.index);
this.groups.push(this.current);
}
};
function ElementGroup(vertexStartIndex, elementStartIndex, secondElementStartIndex) {
// the offset into the vertex buffer of the first vertex in this group
this.vertexStartIndex = vertexStartIndex;
this.elementStartIndex = elementStartIndex;
this.secondElementStartIndex = secondElementStartIndex;
this.elementLength = 0;
this.vertexLength = 0;
this.secondElementLength = 0;
}
},{}],13:[function(require,module,exports){
'use strict';
var rbush = require('rbush');
var Point = require('point-geometry');
var vt = require('vector-tile');
var util = require('../util/util');
module.exports = FeatureTree;
function FeatureTree(coord, overscaling) {
this.x = coord.x;
this.y = coord.y;
this.z = coord.z - Math.log(overscaling) / Math.LN2;
this.rtree = rbush(9);
this.toBeInserted = [];
}
FeatureTree.prototype.insert = function(bbox, layers, feature) {
bbox.layers = layers;
bbox.feature = feature;
this.toBeInserted.push(bbox);
};
// bulk insert into tree
FeatureTree.prototype._load = function() {
this.rtree.load(this.toBeInserted);
this.toBeInserted = [];
};
// Finds features in this tile at a particular position.
FeatureTree.prototype.query = function(args, callback) {
if (this.toBeInserted.length) this._load();
var params = args.params || {},
radius = (params.radius || 0) * 4096 / args.scale,
x = args.x,
y = args.y,
result = [];
var matching = this.rtree.search([ x - radius, y - radius, x + radius, y + radius ]);
for (var i = 0; i < matching.length; i++) {
var feature = matching[i].feature,
layers = matching[i].layers,
type = vt.VectorTileFeature.types[feature.type];
if (params.$type && type !== params.$type)
continue;
if (!geometryContainsPoint(feature.loadGeometry(), type, new Point(x, y), radius))
continue;
var geoJSON = feature.toGeoJSON(this.x, this.y, this.z);
for (var l = 0; l < layers.length; l++) {
var layer = layers[l];
if (params.layer && layer !== params.layer.id)
continue;
result.push(util.extend({layer: layer}, geoJSON));
}
}
callback(null, result);
};
function geometryContainsPoint(rings, type, p, radius) {
return type === 'Point' ? pointContainsPoint(rings, p, radius) :
type === 'LineString' ? lineContainsPoint(rings, p, radius) :
type === 'Polygon' ? polyContainsPoint(rings, p) || lineContainsPoint(rings, p, radius) : false;
}
// Code from http://stackoverflow.com/a/1501725/331379.
function distToSegmentSquared(p, v, w) {
var l2 = v.distSqr(w);
if (l2 === 0) return p.distSqr(v);
var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
if (t < 0) return p.distSqr(v);
if (t > 1) return p.distSqr(w);
return p.distSqr(w.sub(v)._mult(t)._add(v));
}
function lineContainsPoint(rings, p, radius) {
var r = radius * radius;
for (var i = 0; i < rings.length; i++) {
var ring = rings[i];
for (var j = 1; j < ring.length; j++) {
// Find line segments that have a distance <= radius^2 to p
// In that case, we treat the line as "containing point p".
var v = ring[j - 1], w = ring[j];
if (distToSegmentSquared(p, v, w) < r) return true;
}
}
return false;
}
// point in polygon ray casting algorithm
function polyContainsPoint(rings, p) {
var c = false,
ring, p1, p2;
for (var k = 0; k < rings.length; k++) {
ring = rings[k];
for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
p1 = ring[i];
p2 = ring[j];
if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
c = !c;
}
}
}
return c;
}
function pointContainsPoint(rings, p, radius) {
var r = radius * radius;
for (var i = 0; i < rings.length; i++) {
var ring = rings[i];
for (var j = 0; j < ring.length; j++) {
if (ring[j].distSqr(p) <= r) return true;
}
}
return false;
}
},{"../util/util":96,"point-geometry":113,"rbush":114,"vector-tile":117}],14:[function(require,module,exports){
'use strict';
var ElementGroups = require('./element_groups');
module.exports = FillBucket;
function FillBucket(buffers) {
this.buffers = buffers;
this.elementGroups = new ElementGroups(buffers.fillVertex, buffers.fillElement, buffers.outlineElement);
}
FillBucket.prototype.addFeatures = function() {
var features = this.features;
for (var i = 0; i < features.length; i++) {
var feature = features[i];
this.addFeature(feature.loadGeometry());
}
};
FillBucket.prototype.addFeature = function(lines) {
for (var i = 0; i < lines.length; i++) {
this.addFill(lines[i]);
}
};
FillBucket.prototype.addFill = function(vertices) {
if (vertices.length < 3) {
//console.warn('a fill must have at least three vertices');
return;
}
// Calculate the total number of vertices we're going to produce so that we
// can resize the buffer beforehand, or detect whether the current line
// won't fit into the buffer anymore.
// In order to be able to use the vertex buffer for drawing the antialiased
// outlines, we separate all polygon vertices with a degenerate (out-of-
// viewplane) vertex.
var len = vertices.length;
// Check whether this geometry buffer can hold all the required vertices.
this.elementGroups.makeRoomFor(len + 1);
var elementGroup = this.elementGroups.current;
var fillVertex = this.buffers.fillVertex;
var fillElement = this.buffers.fillElement;
var outlineElement = this.buffers.outlineElement;
// We're generating triangle fans, so we always start with the first coordinate in this polygon.
var firstIndex = fillVertex.index - elementGroup.vertexStartIndex,
prevIndex, currentIndex, currentVertex;
for (var i = 0; i < vertices.length; i++) {
currentIndex = fillVertex.index - elementGroup.vertexStartIndex;
currentVertex = vertices[i];
fillVertex.add(currentVertex.x, currentVertex.y);
elementGroup.vertexLength++;
// Only add triangles that have distinct vertices.
if (i >= 2 && (currentVertex.x !== vertices[0].x || currentVertex.y !== vertices[0].y)) {
fillElement.add(firstIndex, prevIndex, currentIndex);
elementGroup.elementLength++;
}
if (i >= 1) {
outlineElement.add(prevIndex, currentIndex);
elementGroup.secondElementLength++;
}
prevIndex = currentIndex;
}
};
},{"./element_groups":12}],15:[function(require,module,exports){
'use strict';
var ElementGroups = require('./element_groups');
module.exports = LineBucket;
function LineBucket(buffers, layoutProperties) {
this.buffers = buffers;
this.elementGroups = new ElementGroups(buffers.lineVertex, buffers.lineElement);
this.layoutProperties = layoutProperties;
}
LineBucket.prototype.addFeatures = function() {
var features = this.features;
for (var i = 0; i < features.length; i++) {
var feature = features[i];
this.addFeature(feature.loadGeometry());
}
};
LineBucket.prototype.addFeature = function(lines) {
var layoutProperties = this.layoutProperties;
for (var i = 0; i < lines.length; i++) {
this.addLine(lines[i],
layoutProperties['line-join'],
layoutProperties['line-cap'],
layoutProperties['line-miter-limit'],
layoutProperties['line-round-limit']);
}
};
LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLimit) {
var len = vertices.length;
// If the line has duplicate vertices at the end, adjust length to remove them.
while (len > 2 && vertices[len - 1].equals(vertices[len - 2])) {
len--;
}
if (vertices.length < 2) {
//console.warn('a line must have at least two vertices');
return;
}
if (join === 'bevel') miterLimit = 1.05;
var firstVertex = vertices[0],
lastVertex = vertices[len - 1],
closed = firstVertex.equals(lastVertex);
// we could be more precise, but it would only save a negligible amount of space
this.elementGroups.makeRoomFor(len * 4);
if (len === 2 && closed) {
// console.warn('a line may not have coincident points');
return;
}
var beginCap = cap,
endCap = closed ? 'butt' : cap,
flip = 1,
distance = 0,
startOfLine = true,
currentVertex, prevVertex, nextVertex, prevNormal, nextNormal, offsetA, offsetB;
// the last three vertices added
this.e1 = this.e2 = this.e3 = -1;
if (closed) {
currentVertex = vertices[len - 2];
nextNormal = firstVertex.sub(currentVertex)._unit()._perp();
}
for (var i = 0; i < len; i++) {
nextVertex = closed && i === len - 1 ?
vertices[1] : // if the line is closed, we treat the last vertex like the first
vertices[i + 1]; // just the next vertex
// if two consecutive vertices exist, skip the current one
if (nextVertex && vertices[i].equals(nextVertex)) continue;
if (nextNormal) prevNormal = nextNormal;
if (currentVertex) prevVertex = currentVertex;
currentVertex = vertices[i];
// Calculate how far along the line the currentVertex is
if (prevVertex) distance += currentVertex.dist(prevVertex);
// Calculate the normal towards the next vertex in this line. In case
// there is no next vertex, pretend that the line is continuing straight,
// meaning that we are just using the previous normal.
nextNormal = nextVertex ? nextVertex.sub(currentVertex)._unit()._perp() : prevNormal;
// If we still don't have a previous normal, this is the beginning of a
// non-closed line, so we're doing a straight "join".
prevNormal = prevNormal || nextNormal;
// Determine the normal of the join extrusion. It is the angle bisector
// of the segments between the previous line and the next line.
var joinNormal = prevNormal.add(nextNormal)._unit();
/* joinNormal prevNormal
* ↖ ↑
* .________. prevVertex
* |
* nextNormal ← | currentVertex
* |
* nextVertex !
*
*/
// Calculate the length of the miter (the ratio of the miter to the width).
// Find the cosine of the angle between the next and join normals
// using dot product. The inverse of that is the miter length.
var cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y;
var miterLength = 1 / cosHalfAngle;
// The join if a middle vertex, otherwise the cap.
var middleVertex = prevVertex && nextVertex;
var currentJoin = middleVertex ? join : nextVertex ? beginCap : endCap;
if (middleVertex && currentJoin === 'round' && miterLength < roundLimit) {
currentJoin = 'miter';
}
if (currentJoin === 'miter' && miterLength > miterLimit) {
currentJoin = 'bevel';
}
if (currentJoin === 'bevel') {
// The maximum extrude length is 128 / 63 = 2 times the width of the line
// so if miterLength >= 2 we need to draw a different type of bevel where.
if (miterLength > 2) currentJoin = 'flipbevel';
// If the miterLength is really small and the line bevel wouldn't be visible,
// just draw a miter join to save a triangle.
if (miterLength < miterLimit) currentJoin = 'miter';
}
if (currentJoin === 'miter') {
joinNormal._mult(miterLength);
this.addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false);
} else if (currentJoin === 'flipbevel') {
// miter is too big, flip the direction to make a beveled join
if (miterLength > 100) {
// Almost parallel lines
joinNormal = nextNormal.clone();
} else {
var direction = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x > 0 ? -1 : 1;
var bevelLength = miterLength * prevNormal.add(nextNormal).mag() / prevNormal.sub(nextNormal).mag();
joinNormal._perp()._mult(bevelLength * direction);
}
this.addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false);
flip = -flip;
} else if (currentJoin === 'bevel') {
var dir = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x;
var offset = -Math.sqrt(miterLength * miterLength - 1);
if (flip * dir > 0) {
offsetB = 0;
offsetA = offset;
} else {
offsetA = 0;
offsetB = offset;
}
// Close previous segment with a bevel
if (!startOfLine) {
this.addCurrentVertex(currentVertex, flip, distance, prevNormal, offsetA, offsetB, false);
}
// Start next segment
if (nextVertex) {
this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -offsetA, -offsetB, false);
}
} else if (currentJoin === 'butt') {
if (!startOfLine) {
// Close previous segment with a butt
this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 0, 0, false);
}
// Start next segment with a butt
if (nextVertex) {
this.addCurrentVertex(currentVertex, flip, distance, nextNormal, 0, 0, false);
}
} else if (currentJoin === 'square') {
if (!startOfLine) {
// Close previous segment with a square cap
this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 1, 1, false);
// The segment is done. Unset vertices to disconnect segments.
this.e1 = this.e2 = -1;
flip = 1;
}
// Start next segment
if (nextVertex) {
this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -1, -1, false);
}
} else if (currentJoin === 'round') {
if (!startOfLine) {
// Close previous segment with butt
this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 0, 0, false);
// Add round cap or linejoin at end of segment
this.addCurrentVertex(currentVertex, flip, distance, prevNormal, 1, 1, true);
// The segment is done. Unset vertices to disconnect segments.
this.e1 = this.e2 = -1;
flip = 1;
} else if (beginCap === 'round') {
// Add round cap before first segment
this.addCurrentVertex(currentVertex, flip, distance, nextNormal, -1, -1, true);
}
// Start next segment with a butt
if (nextVertex) {
this.addCurrentVertex(currentVertex, flip, distance, nextNormal, 0, 0, false);
}
}
startOfLine = false;
}
};
/**
* Add two vertices to the buffers.
*
* @param {Object} currentVertex the line vertex to add buffer vertices for
* @param {Number} flip -1 if the vertices should be flipped, 1 otherwise
* @param {Number} distance the distance from the beggining of the line to the vertex
* @param {Number} endLeft extrude to shift the left vertex along the line
* @param {Number} endRight extrude to shift the left vertex along the line
* @param {Boolean} round whether this is a round cap
*/
LineBucket.prototype.addCurrentVertex = function(currentVertex, flip, distance, normal, endLeft, endRight, round) {
var tx = round ? 1 : 0;
var extrude;
var lineVertex = this.buffers.lineVertex;
var lineElement = this.buffers.lineElement;
var elementGroup = this.elementGroups.current;
var vertexStartIndex = this.elementGroups.current.vertexStartIndex;
extrude = normal.mult(flip);
if (endLeft) extrude._sub(normal.perp()._mult(endLeft));
this.e3 = lineVertex.add(currentVertex, extrude, tx, 0, distance) - vertexStartIndex;
if (this.e1 >= 0 && this.e2 >= 0) {
lineElement.add(this.e1, this.e2, this.e3);
elementGroup.elementLength++;
}
this.e1 = this.e2;
this.e2 = this.e3;
extrude = normal.mult(-flip);
if (endRight) extrude._sub(normal.perp()._mult(endRight));
this.e3 = lineVertex.add(currentVertex, extrude, tx, 1, distance) - vertexStartIndex;
if (this.e1 >= 0 && this.e2 >= 0) {
lineElement.add(this.e1, this.e2, this.e3);
elementGroup.elementLength++;
}
this.e1 = this.e2;
this.e2 = this.e3;
elementGroup.vertexLength += 2;
};
},{"./element_groups":12}],16:[function(require,module,exports){
'use strict';
var ElementGroups = require('./element_groups');
var Anchor = require('../symbol/anchor');
var getAnchors = require('../symbol/get_anchors');
var resolveTokens = require('../util/token');
var Quads = require('../symbol/quads');
var Shaping = require('../symbol/shaping');
var resolveText = require('../symbol/resolve_text');
var resolveIcons = require('../symbol/resolve_icons');
var mergeLines = require('../symbol/mergelines');
var shapeText = Shaping.shapeText;
var shapeIcon = Shaping.shapeIcon;
var getGlyphQuads = Quads.getGlyphQuads;
var getIconQuads = Quads.getIconQuads;
var clipLine = require('../symbol/clip_line');
var Point = require('point-geometry');
var CollisionFeature = require('../symbol/collision_feature');
module.exports = SymbolBucket;
function SymbolBucket(buffers, layoutProperties, collision, overscaling, collisionDebug) {
this.buffers = buffers;
this.layoutProperties = layoutProperties;
this.collision = collision;
this.overscaling = overscaling;
this.collisionDebug = collisionDebug;
this.symbolInstances = [];
}
SymbolBucket.prototype.addFeatures = function() {
var layout = this.layoutProperties;
var features = this.features;
var textFeatures = this.textFeatures;
var horizontalAlign = 0.5,
verticalAlign = 0.5;
switch (layout['text-anchor']) {
case 'right':
case 'top-right':
case 'bottom-right':
horizontalAlign = 1;
break;
case 'left':
case 'top-left':
case 'bottom-left':
horizontalAlign = 0;
break;
}
switch (layout['text-anchor']) {
case 'bottom':
case 'bottom-right':
case 'bottom-left':
verticalAlign = 1;
break;
case 'top':
case 'top-right':
case 'top-left':
verticalAlign = 0;
break;
}
var justify = layout['text-justify'] === 'right' ? 1 :
layout['text-justify'] === 'left' ? 0 :
0.5;
var oneEm = 24;
var lineHeight = layout['text-line-height'] * oneEm;
var maxWidth = layout['symbol-placement'] !== 'line' ? layout['text-max-width'] * oneEm : 0;
var spacing = layout['text-letter-spacing'] * oneEm;
var textOffset = [layout['text-offset'][0] * oneEm, layout['text-offset'][1] * oneEm];
var fontstack = layout['text-font'];
var geometries = [];
for (var g = 0; g < features.length; g++) {
geometries.push(features[g].loadGeometry());
}
if (layout['symbol-placement'] === 'line') {
// Merge adjacent lines with the same text to improve labelling.
// It's better to place labels on one long line than on many short segments.
var merged = mergeLines(features, textFeatures, geometries);
geometries = merged.geometries;
features = merged.features;
textFeatures = merged.textFeatures;
}
var shapedText, shapedIcon;
for (var k = 0; k < features.length; k++) {
if (!geometries[k]) continue;
if (textFeatures[k]) {
shapedText = shapeText(textFeatures[k], this.stacks[fontstack], maxWidth,
lineHeight, horizontalAlign, verticalAlign, justify, spacing, textOffset);
} else {
shapedText = null;
}
if (layout['icon-image']) {
var iconName = resolveTokens(features[k].properties, layout['icon-image']);
var image = this.icons[iconName];
shapedIcon = shapeIcon(image, layout);
if (image) {
if (this.sdfIcons === undefined) {
this.sdfIcons = image.sdf;
} else if (this.sdfIcons !== image.sdf) {
console.warn('Style sheet warning: Cannot mix SDF and non-SDF icons in one bucket');
}
}
} else {
shapedIcon = null;
}
if (shapedText || shapedIcon) {
this.addFeature(geometries[k], shapedText, shapedIcon);
}
}
this.placeFeatures(this.buffers, this.collisionDebug);
};
SymbolBucket.prototype.addFeature = function(lines, shapedText, shapedIcon) {
var layout = this.layoutProperties;
var collision = this.collision;
var glyphSize = 24;
var fontScale = layout['text-max-size'] / glyphSize,
textBoxScale = collision.tilePixelRatio * fontScale,
iconBoxScale = collision.tilePixelRatio * layout['icon-max-size'],
symbolMinDistance = collision.tilePixelRatio * layout['symbol-min-distance'],
avoidEdges = layout['symbol-avoid-edges'],
textPadding = layout['text-padding'] * collision.tilePixelRatio,
iconPadding = layout['icon-padding'] * collision.tilePixelRatio,
textMaxAngle = layout['text-max-angle'] / 180 * Math.PI,
textAlongLine = layout['text-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line',
iconAlongLine = layout['icon-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line',
mayOverlap = layout['text-allow-overlap'] || layout['icon-allow-overlap'] ||
layout['text-ignore-placement'] || layout['icon-ignore-placement'];
if (layout['symbol-placement'] === 'line') {
lines = clipLine(lines, 0, 0, 4096, 4096);
}
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
// Calculate the anchor points around which you want to place labels
var anchors = layout['symbol-placement'] === 'line' ?
getAnchors(line, symbolMinDistance, textMaxAngle, shapedText, glyphSize, textBoxScale, this.overscaling) :
[ new Anchor(line[0].x, line[0].y, 0) ];
// For each potential label, create the placement features used to check for collisions, and the quads use for rendering.
for (var j = 0, len = anchors.length; j < len; j++) {
var anchor = anchors[j];
var inside = !(anchor.x < 0 || anchor.x > 4096 || anchor.y < 0 || anchor.y > 4096);
if (avoidEdges && !inside) continue;
// Normally symbol layers are drawn across tile boundaries. Only symbols
// with their anchors within the tile boundaries are added to the buffers
// to prevent symbols from being drawn twice.
//
// Symbols in layers with overlap are sorted in the y direction so that
// symbols lower on the canvas are drawn on top of symbols near the top.
// To preserve this order across tile boundaries these symbols can't
// be drawn across tile boundaries. Instead they need to be included in
// the buffers for both tiles and clipped to tile boundaries at draw time.
var addToBuffers = inside || mayOverlap;
this.symbolInstances.push(new SymbolInstance(anchor, line, shapedText, shapedIcon, layout, addToBuffers,
textBoxScale, textPadding, textAlongLine,
iconBoxScale, iconPadding, iconAlongLine));
}
}
};
SymbolBucket.prototype.placeFeatures = function(buffers, collisionDebug) {
// Calculate which labels can be shown and when they can be shown and
// create the bufers used for rendering.
this.buffers = buffers;
var elementGroups = this.elementGroups = {
text: new ElementGroups(buffers.glyphVertex, buffers.glyphElement),
icon: new ElementGroups(buffers.iconVertex, buffers.iconElement),
sdfIcons: this.sdfIcons
};
var layout = this.layoutProperties;
var collision = this.collision;
var maxScale = this.collision.maxScale;
var textAlongLine = layout['text-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line';
var iconAlongLine = layout['icon-rotation-alignment'] === 'map' && layout['symbol-placement'] === 'line';
var mayOverlap = layout['text-allow-overlap'] || layout['icon-allow-overlap'] ||
layout['text-ignore-placement'] || layout['icon-ignore-placement'];
// Sort symbols by their y position on the canvas so that they lower symbols
// are drawn on top of higher symbols.
// Don't sort symbols that won't overlap because it isn't necessary and
// because it causes more labels to pop in and out when rotating.
if (mayOverlap) {
var angle = this.collision.angle;
var sin = Math.sin(angle),
cos = Math.cos(angle);
this.symbolInstances.sort(function(a, b) {
var aRotated = sin * a.x + cos * a.y;
var bRotated = sin * b.x + cos * b.y;
return bRotated - aRotated;
});
}
for (var p = 0; p < this.symbolInstances.length; p++) {
var symbolInstance = this.symbolInstances[p];
var hasText = symbolInstance.hasText;
var hasIcon = symbolInstance.hasIcon;
var iconWithoutText = layout['text-optional'] || !hasText,
textWithoutIcon = layout['icon-optional'] || !hasIcon;
// Calculate the scales at which the text and icon can be placed without collision.
var glyphScale = hasText && !layout['text-allow-overlap'] ?
collision.placeFeature(symbolInstance.textCollisionFeature) : collision.minScale;
var iconScale = hasIcon && !layout['icon-allow-overlap'] ?
collision.placeFeature(symbolInstance.iconCollisionFeature) : collision.minScale;
// Combine the scales for icons and text.
if (!iconWithoutText && !textWithoutIcon) {
iconScale = glyphScale = Math.max(iconScale, glyphScale);
} else if (!textWithoutIcon && glyphScale) {
glyphScale = Math.max(iconScale, glyphScale);
} else if (!iconWithoutText && iconScale) {
iconScale = Math.max(iconScale, glyphScale);
}
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText) {
if (!layout['text-ignore-placement']) {
collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale);
}
if (glyphScale <= maxScale) {
this.addSymbols(buffers.glyphVertex, buffers.glyphElement, elementGroups.text,
symbolInstance.glyphQuads, glyphScale, layout['text-keep-upright'], textAlongLine);
}
}
if (hasIcon) {
if (!layout['icon-ignore-placement']) {
collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale);
}
if (iconScale <= maxScale) {
this.addSymbols(buffers.iconVertex, buffers.iconElement, elementGroups.icon,
symbolInstance.iconQuads, iconScale, layout['icon-keep-upright'], iconAlongLine);
}
}
}
if (collisionDebug) this.addToDebugBuffers();
};
SymbolBucket.prototype.addSymbols = function(vertex, element, elementGroups, quads, scale, keepUpright, alongLine) {
elementGroups.makeRoomFor(4 * quads.length);
var elementGroup = elementGroups.current;
var zoom = this.collision.zoom;
var placementZoom = Math.max(Math.log(scale) / Math.LN2 + zoom, 0);
var placementAngle = this.collision.angle + Math.PI;
for (var k = 0; k < quads.length; k++) {
var symbol = quads[k],
angle = symbol.angle;
// drop upside down versions of glyphs
var a = (angle + placementAngle) % (Math.PI * 2);
if (keepUpright && alongLine && (a <= Math.PI / 2 || a > Math.PI * 3 / 2)) continue;
var tl = symbol.tl,
tr = symbol.tr,
bl = symbol.bl,
br = symbol.br,
tex = symbol.tex,
anchor = symbol.anchor,
minZoom = Math.max(zoom + Math.log(symbol.minScale) / Math.LN2, placementZoom),
maxZoom = Math.min(zoom + Math.log(symbol.maxScale) / Math.LN2, 25);
if (maxZoom <= minZoom) continue;
// Lower min zoom so that while fading out the label it can be shown outside of collision-free zoom levels
if (minZoom === placementZoom) minZoom = 0;
var triangleIndex = vertex.index - elementGroup.vertexStartIndex;
vertex.add(anchor.x, anchor.y, tl.x, tl.y, tex.x, tex.y, minZoom, maxZoom, placementZoom);
vertex.add(anchor.x, anchor.y, tr.x, tr.y, tex.x + tex.w, tex.y, minZoom, maxZoom, placementZoom);
vertex.add(anchor.x, anchor.y, bl.x, bl.y, tex.x, tex.y + tex.h, minZoom, maxZoom, placementZoom);
vertex.add(anchor.x, anchor.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, minZoom, maxZoom, placementZoom);
elementGroup.vertexLength += 4;
element.add(triangleIndex, triangleIndex + 1, triangleIndex + 2);
element.add(triangleIndex + 1, triangleIndex + 2, triangleIndex + 3);
elementGroup.elementLength += 2;
}
};
SymbolBucket.prototype.getDependencies = function(tile, actor, callback) {
var firstdone = false;
this.getTextDependencies(tile, actor, done);
this.getIconDependencies(tile, actor, done);
function done(err) {
if (err || firstdone) return callback(err);
firstdone = true;
}
};
SymbolBucket.prototype.getIconDependencies = function(tile, actor, callback) {
if (this.layoutProperties['icon-image']) {
var features = this.features;
var icons = resolveIcons(features, this.layoutProperties);
if (icons.length) {
actor.send('get icons', { icons: icons }, setIcons.bind(this));
} else {
callback();
}
} else {
callback();
}
function setIcons(err, newicons) {
if (err) return callback(err);
this.icons = newicons;
callback();
}
};
SymbolBucket.prototype.getTextDependencies = function(tile, actor, callback) {
var features = this.features;
var fontstack = this.layoutProperties['text-font'];
var stacks = this.stacks = tile.stacks;
if (stacks[fontstack] === undefined) {
stacks[fontstack] = {};
}
var stack = stacks[fontstack];
var data = resolveText(features, this.layoutProperties, stack);
this.textFeatures = data.textFeatures;
actor.send('get glyphs', {
uid: tile.uid,
fontstack: fontstack,
codepoints: data.codepoints
}, function(err, newstack) {
if (err) return callback(err);
for (var codepoint in newstack) {
stack[codepoint] = newstack[codepoint];
}
callback();
});
};
SymbolBucket.prototype.addToDebugBuffers = function() {
this.elementGroups.collisionBox = new ElementGroups(this.buffers.collisionBoxVertex);
this.elementGroups.collisionBox.makeRoomFor(0);
var buffer = this.buffers.collisionBoxVertex;
var angle = -this.collision.angle;
var yStretch = this.collision.yStretch;
for (var j = 0; j < this.symbolInstances.length; j++) {
for (var i = 0; i < 2; i++) {
var feature = this.symbolInstances[j][i === 0 ? 'textCollisionFeature' : 'iconCollisionFeature'];
if (!feature) continue;
var boxes = feature.boxes;
for (var b = 0; b < boxes.length; b++) {
var box = boxes[b];
var anchor = box.anchor;
var tl = new Point(box.x1, box.y1 * yStretch)._rotate(angle);
var tr = new Point(box.x2, box.y1 * yStretch)._rotate(angle);
var bl = new Point(box.x1, box.y2 * yStretch)._rotate(angle);
var br = new Point(box.x2, box.y2 * yStretch)._rotate(angle);
var maxZoom = Math.max(0, Math.min(25, this.collision.zoom + Math.log(box.maxScale) / Math.LN2));
var placementZoom = Math.max(0, Math.min(25, this.collision.zoom + Math.log(box.placementScale) / Math.LN2));
buffer.add(anchor, tl, maxZoom, placementZoom);
buffer.add(anchor, tr, maxZoom, placementZoom);
buffer.add(anchor, tr, maxZoom, placementZoom);
buffer.add(anchor, br, maxZoom, placementZoom);
buffer.add(anchor, br, maxZoom, placementZoom);
buffer.add(anchor, bl, maxZoom, placementZoom);
buffer.add(anchor, bl, maxZoom, placementZoom);
buffer.add(anchor, tl, maxZoom, placementZoom);
this.elementGroups.collisionBox.current.vertexLength += 8;
}
}
}
};
function SymbolInstance(anchor, line, shapedText, shapedIcon, layout, addToBuffers,
textBoxScale, textPadding, textAlongLine,
iconBoxScale, iconPadding, iconAlongLine) {
this.x = anchor.x;
this.y = anchor.y;
this.hasText = !!shapedText;
this.hasIcon = !!shapedIcon;
if (this.hasText) {
this.glyphQuads = addToBuffers ? getGlyphQuads(anchor, shapedText, textBoxScale, line, layout, textAlongLine) : [];
this.textCollisionFeature = new CollisionFeature(line, anchor, shapedText, textBoxScale, textPadding, textAlongLine);
}
if (this.hasIcon) {
this.iconQuads = addToBuffers ? getIconQuads(anchor, shapedIcon, iconBoxScale, line, layout, iconAlongLine) : [];
this.iconCollisionFeature = new CollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine);
}
}
},{"../symbol/anchor":58,"../symbol/clip_line":61,"../symbol/collision_feature":63,"../symbol/get_anchors":65,"../symbol/mergelines":68,"../symbol/quads":69,"../symbol/resolve_icons":70,"../symbol/resolve_text":71,"../symbol/shaping":72,"../util/token":95,"./element_groups":12,"point-geometry":113}],17:[function(require,module,exports){
'use strict';
module.exports = Coordinate;
/**
* A coordinate is a column, row, zoom combination, often used
* as the data component of a tile.
*
* @param {Number} column
* @param {Number} row
* @param {Number} zoom
* @private
*/
function Coordinate(column, row, zoom) {
this.column = column;
this.row = row;
this.zoom = zoom;
}
Coordinate.prototype = {
/**
* Create a clone of this coordinate that can be mutated without
* changing the original coordinate
*
* @returns {Coordinate} clone
* @private
* var coord = new Coordinate(0, 0, 0);
* var c2 = coord.clone();
* // since coord is cloned, modifying a property of c2 does
* // not modify it.
* c2.zoom = 2;
*/
clone: function() {
return new Coordinate(this.column, this.row, this.zoom);
},
/**
* Zoom this coordinate to a given zoom level. This returns a new
* coordinate object, not mutating the old one.
*
* @param {Number} zoom
* @returns {Coordinate} zoomed coordinate
* @private
* @example
* var coord = new Coordinate(0, 0, 0);
* var c2 = coord.zoomTo(1);
* c2 // equals new Coordinate(0, 0, 1);
*/
zoomTo: function(zoom) { return this.clone()._zoomTo(zoom); },
/**
* Subtract the column and row values of this coordinate from those
* of another coordinate. The other coordinat will be zoomed to the
* same level as `this` before the subtraction occurs
*
* @param {Coordinate} c other coordinate
* @returns {Coordinate} result
* @private
*/
sub: function(c) { return this.clone()._sub(c); },
_zoomTo: function(zoom) {
var scale = Math.pow(2, zoom - this.zoom);
this.column *= scale;
this.row *= scale;
this.zoom = zoom;
return this;
},
_sub: function(c) {
c = c.zoomTo(this.zoom);
this.column -= c.column;
this.row -= c.row;
return this;
}
};
},{}],18:[function(require,module,exports){
'use strict';
module.exports = LatLng;
var wrap = require('../util/util').wrap;
/**
* Create a latitude, longitude object from a given latitude and longitude pair in degrees.
*
* @class LatLng
* @classdesc A representation of a latitude and longitude point, in degrees.
* @param {number} lat latitude
* @param {number} lng longitude
* @example
* var latlng = new mapboxgl.LatLng(37.76, -122.44);
*/
function LatLng(lat, lng) {
if (isNaN(lat) || isNaN(lng)) {
throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
}
this.lat = +lat;
this.lng = +lng;
}
/**
* Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180).
*
* @returns {LatLng} wrapped LatLng object
* @example
* var point = mapboxgl.LatLng(0, 200);
* var wrapped = point.wrap();
* wrapped.lng; // = -160
*/
LatLng.prototype.wrap = function () {
return new LatLng(this.lat, wrap(this.lng, -180, 180));
};
/**
* Convert an array to a `LatLng` object, or return an existing `LatLng` object
* unchanged.
*
* @param {Array<number>|LatLng} input `input` to convert
* @returns {LatLng} LatLng object or original input
* @example
* var ll = mapboxgl.LatLng.convert([10, 10]);
* var ll2 = new mapboxgl.LatLng(10, 10);
* ll // = ll2
*/
LatLng.convert = function (input) {
if (input instanceof LatLng) {
return input;
}
if (Array.isArray(input)) {
return new LatLng(input[0], input[1]);
}
return input;
};
},{"../util/util":96}],19:[function(require,module,exports){
'use strict';
module.exports = LatLngBounds;
var LatLng = require('./lat_lng');
/**
* Creates a bounding box from the given pair of points. If parameteres are omitted, a `null` bounding box is created.
*
* @class LatLngBounds
* @classdesc A representation of rectangular box on the earth, defined by its southwest and northeast points in latitude and longitude.
* @param {LatLng} sw southwest
* @param {LatLng} ne northeast
* @example
* var sw = new mapboxgl.LatLng(0, 0);
* var ne = new mapboxgl.LatLng(10, -10);
* var bounds = new mapboxgl.LatLngBounds(sw, ne);
*
*/
function LatLngBounds(sw, ne) {
if (!sw) return;
var latlngs = ne ? [sw, ne] : sw;
for (var i = 0, len = latlngs.length; i < len; i++) {
this.extend(latlngs[i]);
}
}
LatLngBounds.prototype = {
/**
* Extend the bounds to include a given LatLng or LatLngBounds.
*
* @param {LatLng|LatLngBounds} obj object to extend to
* @returns {LatLngBounds} `this`
*/
extend: function(obj) {
var sw = this._sw,
ne = this._ne,
sw2, ne2;
if (obj instanceof LatLng) {
sw2 = obj;
ne2 = obj;
} else if (obj instanceof LatLngBounds) {
sw2 = obj._sw;
ne2 = obj._ne;
if (!sw2 || !ne2) return this;
} else {
return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;
}
if (!sw && !ne) {
this._sw = new LatLng(sw2.lat, sw2.lng);
this._ne = new LatLng(ne2.lat, ne2.lng);
} else {
sw.lat = Math.min(sw2.lat, sw.lat);
sw.lng = Math.min(sw2.lng, sw.lng);
ne.lat = Math.max(ne2.lat, ne.lat);
ne.lng = Math.max(ne2.lng, ne.lng);
}
return this;
},
/**
* Get the point equidistant from this box's corners
* @returns {LatLng} centerpoint
* @example
* var bounds = new mapboxgl.LatLngBounds(
* new mapboxgl.LatLng(10, 10),
* new mapboxgl.LatLng(-10, -10);
* bounds.getCenter(); // equals mapboxgl.LatLng(0, 0)
*/
getCenter: function() {
return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);
},
/**
* Get southwest corner
* @returns {LatLng} southwest
*/
getSouthWest: function() { return this._sw; },
/**
* Get northeast corner
* @returns {LatLng} northeast
*/
getNorthEast: function() { return this._ne; },
/**
* Get northwest corner
* @returns {LatLng} northwest
*/
getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },
/**
* Get southeast corner
* @returns {LatLng} southeast
*/
getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },
/**
* Get west edge longitude
* @returns {number} west
*/
getWest: function() { return this._sw.lng; },
/**
* Get south edge latitude
* @returns {number} south
*/
getSouth: function() { return this._sw.lat; },
/**
* Get east edge longitude
* @returns {number} east
*/
getEast: function() { return this._ne.lng; },
/**
* Get north edge latitude
* @returns {number} north
*/
getNorth: function() { return this._ne.lat; }
};
/**
* constructs LatLngBounds from an array if necessary
* @param {LatLngBounds|*} a any input
* @returns {LatLngBounds|false}
* @example
* // calls LatLng.convert internally to
* // support arrays as latlng values
* LatLngBounds.convert([[-10, -10], [10, 10]]);
*/
LatLngBounds.convert = function (a) {
if (!a || a instanceof LatLngBounds) return a;
return new LatLngBounds(a);
};
},{"./lat_lng":18}],20:[function(require,module,exports){
'use strict';
var LatLng = require('./lat_lng'),
Point = require('point-geometry'),
Coordinate = require('./coordinate'),
wrap = require('../util/util').wrap,
interp = require('../util/interpolate'),
vec4 = require('gl-matrix').vec4,
mat4 = require('gl-matrix').mat4;
module.exports = Transform;
/*
* A single transform, generally used for a single tile to be
* scaled, rotated, and zoomed.
*
* @param {Number} minZoom
* @param {Number} maxZoom
* @private
*/
function Transform(minZoom, maxZoom) {
this.tileSize = 512; // constant
this._minZoom = minZoom || 0;
this._maxZoom = maxZoom || 22;
this.latRange = [-85.05113, 85.05113];
this.width = 0;
this.height = 0;
this.zoom = 0;
this.center = new LatLng(0, 0);
this.angle = 0;
this._altitude = 1.5;
this._pitch = 0;
}
Transform.prototype = {
get minZoom() { return this._minZoom; },
set minZoom(zoom) {
this._minZoom = zoom;
this.zoom = Math.max(this.zoom, zoom);
},
get maxZoom() { return this._maxZoom; },
set maxZoom(zoom) {
this._maxZoom = zoom;
this.zoom = Math.min(this.zoom, zoom);
},
get worldSize() {
return this.tileSize * this.scale;
},
get centerPoint() {
return this.size._div(2);
},
get size() {
return new Point(this.width, this.height);
},
get bearing() {
return -this.angle / Math.PI * 180;
},
set bearing(bearing) {
this.angle = -wrap(bearing, -180, 180) * Math.PI / 180;
},
get pitch() {
return this._pitch / Math.PI * 180;
},
set pitch(pitch) {
this._pitch = Math.min(60, pitch) / 180 * Math.PI;
},
get altitude() {
return this._altitude;
},
set altitude(altitude) {
this._altitude = Math.max(0.75, altitude);
},
get zoom() { return this._zoom; },
set zoom(zoom) {
zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom);
this._zoom = zoom;
this.scale = this.zoomScale(zoom);
this.tileZoom = Math.floor(zoom);
this.zoomFraction = zoom - this.tileZoom;
this._constrain();
},
zoomScale: function(zoom) { return Math.pow(2, zoom); },
scaleZoom: function(scale) { return Math.log(scale) / Math.LN2; },
project: function(latlng, worldSize) {
return new Point(
this.lngX(latlng.lng, worldSize),
this.latY(latlng.lat, worldSize));
},
unproject: function(point, worldSize) {
return new LatLng(
this.yLat(point.y, worldSize),
this.xLng(point.x, worldSize));
},
get x() { return this.lngX(this.center.lng); },
get y() { return this.latY(this.center.lat); },
get point() { return new Point(this.x, this.y); },
/**
* lat/lon <-> absolute pixel coords conversion
* @param {Number} lon
* @param {Number} [worldSize=this.worldSize]
* @returns {Number} pixel coordinate
* @private
*/
lngX: function(lon, worldSize) {
return (180 + lon) * (worldSize || this.worldSize) / 360;
},
/**
* latitude to absolute y coord
*
* @param {Number} lat
* @param {Number} [worldSize=this.worldSize]
* @returns {Number} pixel coordinate
* @private
*/
latY: function(lat, worldSize) {
var y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
return (180 - y) * (worldSize || this.worldSize) / 360;
},
xLng: function(x, worldSize) {
return x * 360 / (worldSize || this.worldSize) - 180;
},
yLat: function(y, worldSize) {
var y2 = 180 - y * 360 / (worldSize || this.worldSize);
return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
},
panBy: function(offset) {
var point = this.centerPoint._add(offset);
this.center = this.pointLocation(point);
this._constrain();
},
setLocationAtPoint: function(latlng, point) {
var c = this.locationCoordinate(latlng);
var coordAtPoint = this.pointCoordinate(point);
var coordCenter = this.pointCoordinate(this.centerPoint);
var translate = coordAtPoint._sub(c);
this.center = this.coordinateLocation(coordCenter._sub(translate));
this._constrain();
},
setZoomAround: function(zoom, center) {
var p = this.locationPoint(center);
this.zoom = zoom;
this.setLocationAtPoint(center, p);
},
setBearingAround: function(bearing, center) {
var p = this.locationPoint(center);
this.bearing = bearing;
this.setLocationAtPoint(center, p);
},
/**
* Given a location, return the screen point that corresponds to it
* @param {LatLng} latlng location
* @returns {Point} screen point
*/
locationPoint: function(latlng) {
return this.coordinatePoint(this.locationCoordinate(latlng));
},
/**
* Given a point on screen, return its latlng
* @param {Point} p screen point
* @returns {LatLng} latlng location
*/
pointLocation: function(p) {
return this.coordinateLocation(this.pointCoordinate(p));
},
/**
* Given a geographical latlng, return an unrounded
* coordinate that represents it at this transform's zoom level and
* worldsize.
* @param {LatLng} latlng
* @returns {Coordinate}
*/
locationCoordinate: function(latlng) {
var k = this.zoomScale(this.tileZoom) / this.worldSize;
return new Coordinate(
this.lngX(latlng.lng) * k,
this.latY(latlng.lat) * k,
this.tileZoom);
},
/**
* Given a Coordinate, return its geographical position.
* @param {Coordinate} coord
* @returns {LatLng} latlng
*/
coordinateLocation: function(coord) {
var worldSize = this.zoomScale(coord.zoom);
return new LatLng(
this.yLat(coord.row, worldSize),
this.xLng(coord.column, worldSize));
},
pointCoordinate: function(p, targetZ) {
if (targetZ === undefined) targetZ = 0;
var matrix = this.coordinatePointMatrix(this.tileZoom);
var inverted = mat4.invert(new Float64Array(16), matrix);
if (!inverted) throw "failed to invert matrix";
// since we don't know the correct projected z value for the point,
// unproject two points to get a line and then find the point on that
// line with z=0
var coord0 = vec4.transformMat4([], [p.x, p.y, 0, 1], inverted);
var coord1 = vec4.transformMat4([], [p.x, p.y, 1, 1], inverted);
var w0 = coord0[3];
var w1 = coord1[3];
var x0 = coord0[0] / w0;
var x1 = coord1[0] / w1;
var y0 = coord0[1] / w0;
var y1 = coord1[1] / w1;
var z0 = coord0[2] / w0;
var z1 = coord1[2] / w1;
var t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0);
return new Coordinate(
interp(x0, x1, t),
interp(y0, y1, t),
this.tileZoom);
},
/**
* Given a coordinate, return the screen point that corresponds to it
* @param {Coordinate} coord
* @returns {Point} screen point
*/
coordinatePoint: function(coord) {
var matrix = this.coordinatePointMatrix(coord.zoom);
var p = vec4.transformMat4([], [coord.column, coord.row, 0, 1], matrix);
return new Point(p[0] / p[3], p[1] / p[3]);
},
coordinatePointMatrix: function(z) {
var proj = this.getProjMatrix();
var scale = this.worldSize / this.zoomScale(z);
mat4.scale(proj, proj, [scale, scale, 1]);
mat4.multiply(proj, this.getPixelMatrix(), proj);
return proj;
},
/**
* converts gl coordinates -1..1 to pixels 0..width
* @returns {Object} matrix
*/
getPixelMatrix: function() {
var m = mat4.create();
mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]);
mat4.translate(m, m, [1, -1, 0]);
return m;
},
_constrain: function() {
if (!this.center) return;
var minY, maxY, minX, maxX, sy, sx, x2, y2,
size = this.size;
if (this.latRange) {
minY = this.latY(this.latRange[1]);
maxY = this.latY(this.latRange[0]);
sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0;
}
if (this.lngRange) {
minX = this.lngX(this.lngRange[0]);
maxX = this.lngX(this.lngRange[1]);
sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0;
}
// how much the map should scale to fit the screen into given latitude/longitude ranges
var s = Math.max(sx || 0, sy || 0);
if (s) {
this.center = this.unproject(new Point(
sx ? (maxX + minX) / 2 : this.x,
sy ? (maxY + minY) / 2 : this.y));
this.zoom += this.scaleZoom(s);
return;
}
if (this.latRange) {
var y = this.y,
h2 = size.y / 2;
if (y - h2 < minY) y2 = minY + h2;
if (y + h2 > maxY) y2 = maxY - h2;
}
if (this.lngRange) {
var x = this.x,
w2 = size.x / 2;
if (x - w2 < minX) x2 = minX + w2;
if (x + w2 > maxX) x2 = maxX - w2;
}
// pan the map if the screen goes off the range
if (x2 !== undefined || y2 !== undefined) {
this.center = this.unproject(new Point(
x2 !== undefined ? x2 : this.x,
y2 !== undefined ? y2 : this.y));
}
},
getProjMatrix: function() {
var m = new Float64Array(16);
// Find the distance from the center point to the center top in altitude units using law of sines.
var halfFov = Math.atan(0.5 / this.altitude);
var topHalfSurfaceDistance = Math.sin(halfFov) * this.altitude / Math.sin(Math.PI / 2 - this._pitch - halfFov);
// Calculate z value of the farthest fragment that should be rendered.
var farZ = Math.cos(Math.PI / 2 - this._pitch) * topHalfSurfaceDistance + this.altitude;
mat4.perspective(m, 2 * Math.atan((this.height / 2) / this.altitude), this.width / this.height, 0.1, farZ);
mat4.translate(m, m, [0, 0, -this.altitude]);
// After the rotateX, z values are in pixel units. Convert them to
// altitude unites. 1 altitude unit = the screen height.
mat4.scale(m, m, [1, -1, 1 / this.height]);
mat4.rotateX(m, m, this._pitch);
mat4.rotateZ(m, m, this.angle);
mat4.translate(m, m, [-this.x, -this.y, 0]);
return m;
}
};
},{"../util/interpolate":92,"../util/util":96,"./coordinate":17,"./lat_lng":18,"gl-matrix":104,"point-geometry":113}],21:[function(require,module,exports){
'use strict';
// Font data From Hershey Simplex Font
// http://paulbourke.net/dataformats/hershey/
var simplexFont = {
" ": [16, []],
"!": [10, [5, 21, 5, 7, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]],
"\"": [16, [4, 21, 4, 14, -1, -1, 12, 21, 12, 14]],
"#": [21, [11, 25, 4, -7, -1, -1, 17, 25, 10, -7, -1, -1, 4, 12, 18, 12, -1, -1, 3, 6, 17, 6]],
"$": [20, [8, 25, 8, -4, -1, -1, 12, 25, 12, -4, -1, -1, 17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]],
"%": [24, [21, 21, 3, 0, -1, -1, 8, 21, 10, 19, 10, 17, 9, 15, 7, 14, 5, 14, 3, 16, 3, 18, 4, 20, 6, 21, 8, 21, 10, 20, 13, 19, 16, 19, 19, 20, 21, 21, -1, -1, 17, 7, 15, 6, 14, 4, 14, 2, 16, 0, 18, 0, 20, 1, 21, 3, 21, 5, 19, 7, 17, 7]],
"&": [26, [23, 12, 23, 13, 22, 14, 21, 14, 20, 13, 19, 11, 17, 6, 15, 3, 13, 1, 11, 0, 7, 0, 5, 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9, 12, 13, 13, 14, 14, 16, 14, 18, 13, 20, 11, 21, 9, 20, 8, 18, 8, 16, 9, 13, 11, 10, 16, 3, 18, 1, 20, 0, 22, 0, 23, 1, 23, 2]],
"'": [10, [5, 19, 4, 20, 5, 21, 6, 20, 6, 18, 5, 16, 4, 15]],
"(": [14, [11, 25, 9, 23, 7, 20, 5, 16, 4, 11, 4, 7, 5, 2, 7, -2, 9, -5, 11, -7]],
")": [14, [3, 25, 5, 23, 7, 20, 9, 16, 10, 11, 10, 7, 9, 2, 7, -2, 5, -5, 3, -7]],
"*": [16, [8, 21, 8, 9, -1, -1, 3, 18, 13, 12, -1, -1, 13, 18, 3, 12]],
"+": [26, [13, 18, 13, 0, -1, -1, 4, 9, 22, 9]],
",": [10, [6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]],
"-": [26, [4, 9, 22, 9]],
".": [10, [5, 2, 4, 1, 5, 0, 6, 1, 5, 2]],
"/": [22, [20, 25, 2, -7]],
"0": [20, [9, 21, 6, 20, 4, 17, 3, 12, 3, 9, 4, 4, 6, 1, 9, 0, 11, 0, 14, 1, 16, 4, 17, 9, 17, 12, 16, 17, 14, 20, 11, 21, 9, 21]],
"1": [20, [6, 17, 8, 18, 11, 21, 11, 0]],
"2": [20, [4, 16, 4, 17, 5, 19, 6, 20, 8, 21, 12, 21, 14, 20, 15, 19, 16, 17, 16, 15, 15, 13, 13, 10, 3, 0, 17, 0]],
"3": [20, [5, 21, 16, 21, 10, 13, 13, 13, 15, 12, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]],
"4": [20, [13, 21, 3, 7, 18, 7, -1, -1, 13, 21, 13, 0]],
"5": [20, [15, 21, 5, 21, 4, 12, 5, 13, 8, 14, 11, 14, 14, 13, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4]],
"6": [20, [16, 18, 15, 20, 12, 21, 10, 21, 7, 20, 5, 17, 4, 12, 4, 7, 5, 3, 7, 1, 10, 0, 11, 0, 14, 1, 16, 3, 17, 6, 17, 7, 16, 10, 14, 12, 11, 13, 10, 13, 7, 12, 5, 10, 4, 7]],
"7": [20, [17, 21, 7, 0, -1, -1, 3, 21, 17, 21]],
"8": [20, [8, 21, 5, 20, 4, 18, 4, 16, 5, 14, 7, 13, 11, 12, 14, 11, 16, 9, 17, 7, 17, 4, 16, 2, 15, 1, 12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6, 11, 9, 12, 13, 13, 15, 14, 16, 16, 16, 18, 15, 20, 12, 21, 8, 21]],
"9": [20, [16, 14, 15, 11, 13, 9, 10, 8, 9, 8, 6, 9, 4, 11, 3, 14, 3, 15, 4, 18, 6, 20, 9, 21, 10, 21, 13, 20, 15, 18, 16, 14, 16, 9, 15, 4, 13, 1, 10, 0, 8, 0, 5, 1, 4, 3]],
":": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2]],
";": [10, [5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4]],
"<": [24, [20, 18, 4, 9, 20, 0]],
"=": [26, [4, 12, 22, 12, -1, -1, 4, 6, 22, 6]],
">": [24, [4, 18, 20, 9, 4, 0]],
"?": [18, [3, 16, 3, 17, 4, 19, 5, 20, 7, 21, 11, 21, 13, 20, 14, 19, 15, 17, 15, 15, 14, 13, 13, 12, 9, 10, 9, 7, -1, -1, 9, 2, 8, 1, 9, 0, 10, 1, 9, 2]],
"@": [27, [18, 13, 17, 15, 15, 16, 12, 16, 10, 15, 9, 14, 8, 11, 8, 8, 9, 6, 11, 5, 14, 5, 16, 6, 17, 8, -1, -1, 12, 16, 10, 14, 9, 11, 9, 8, 10, 6, 11, 5, -1, -1, 18, 16, 17, 8, 17, 6, 19, 5, 21, 5, 23, 7, 24, 10, 24, 12, 23, 15, 22, 17, 20, 19, 18, 20, 15, 21, 12, 21, 9, 20, 7, 19, 5, 17, 4, 15, 3, 12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1, 12, 0, 15, 0, 18, 1, 20, 2, 21, 3, -1, -1, 19, 16, 18, 8, 18, 6, 19, 5]],
"A": [18, [9, 21, 1, 0, -1, -1, 9, 21, 17, 0, -1, -1, 4, 7, 14, 7]],
"B": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, -1, -1, 4, 11, 13, 11, 16, 10, 17, 9, 18, 7, 18, 4, 17, 2, 16, 1, 13, 0, 4, 0]],
"C": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5]],
"D": [21, [4, 21, 4, 0, -1, -1, 4, 21, 11, 21, 14, 20, 16, 18, 17, 16, 18, 13, 18, 8, 17, 5, 16, 3, 14, 1, 11, 0, 4, 0]],
"E": [19, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11, -1, -1, 4, 0, 17, 0]],
"F": [18, [4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11]],
"G": [21, [18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 18, 8, -1, -1, 13, 8, 18, 8]],
"H": [22, [4, 21, 4, 0, -1, -1, 18, 21, 18, 0, -1, -1, 4, 11, 18, 11]],
"I": [8, [4, 21, 4, 0]],
"J": [16, [12, 21, 12, 5, 11, 2, 10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7]],
"K": [21, [4, 21, 4, 0, -1, -1, 18, 21, 4, 7, -1, -1, 9, 12, 18, 0]],
"L": [17, [4, 21, 4, 0, -1, -1, 4, 0, 16, 0]],
"M": [24, [4, 21, 4, 0, -1, -1, 4, 21, 12, 0, -1, -1, 20, 21, 12, 0, -1, -1, 20, 21, 20, 0]],
"N": [22, [4, 21, 4, 0, -1, -1, 4, 21, 18, 0, -1, -1, 18, 21, 18, 0]],
"O": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21]],
"P": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 14, 17, 12, 16, 11, 13, 10, 4, 10]],
"Q": [22, [9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, -1, -1, 12, 4, 18, -2]],
"R": [21, [4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, 11, 4, 11, -1, -1, 11, 11, 18, 0]],
"S": [20, [17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3]],
"T": [16, [8, 21, 8, 0, -1, -1, 1, 21, 15, 21]],
"U": [22, [4, 21, 4, 6, 5, 3, 7, 1, 10, 0, 12, 0, 15, 1, 17, 3, 18, 6, 18, 21]],
"V": [18, [1, 21, 9, 0, -1, -1, 17, 21, 9, 0]],
"W": [24, [2, 21, 7, 0, -1, -1, 12, 21, 7, 0, -1, -1, 12, 21, 17, 0, -1, -1, 22, 21, 17, 0]],
"X": [20, [3, 21, 17, 0, -1, -1, 17, 21, 3, 0]],
"Y": [18, [1, 21, 9, 11, 9, 0, -1, -1, 17, 21, 9, 11]],
"Z": [20, [17, 21, 3, 0, -1, -1, 3, 21, 17, 21, -1, -1, 3, 0, 17, 0]],
"[": [14, [4, 25, 4, -7, -1, -1, 5, 25, 5, -7, -1, -1, 4, 25, 11, 25, -1, -1, 4, -7, 11, -7]],
"\\": [14, [0, 21, 14, -3]],
"]": [14, [9, 25, 9, -7, -1, -1, 10, 25, 10, -7, -1, -1, 3, 25, 10, 25, -1, -1, 3, -7, 10, -7]],
"^": [16, [6, 15, 8, 18, 10, 15, -1, -1, 3, 12, 8, 17, 13, 12, -1, -1, 8, 17, 8, 0]],
"_": [16, [0, -2, 16, -2]],
"`": [10, [6, 21, 5, 20, 4, 18, 4, 16, 5, 15, 6, 16, 5, 17]],
"a": [19, [15, 14, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"b": [19, [4, 21, 4, 0, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]],
"c": [18, [15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"d": [19, [15, 21, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"e": [18, [3, 8, 15, 8, 15, 10, 14, 12, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"f": [12, [10, 21, 8, 21, 6, 20, 5, 17, 5, 0, -1, -1, 2, 14, 9, 14]],
"g": [19, [15, 14, 15, -2, 14, -5, 13, -6, 11, -7, 8, -7, 6, -6, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"h": [19, [4, 21, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]],
"i": [8, [3, 21, 4, 20, 5, 21, 4, 22, 3, 21, -1, -1, 4, 14, 4, 0]],
"j": [10, [5, 21, 6, 20, 7, 21, 6, 22, 5, 21, -1, -1, 6, 14, 6, -3, 5, -6, 3, -7, 1, -7]],
"k": [17, [4, 21, 4, 0, -1, -1, 14, 14, 4, 4, -1, -1, 8, 8, 15, 0]],
"l": [8, [4, 21, 4, 0]],
"m": [30, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, 15, 10, 18, 13, 20, 14, 23, 14, 25, 13, 26, 10, 26, 0]],
"n": [19, [4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0]],
"o": [19, [8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, 16, 6, 16, 8, 15, 11, 13, 13, 11, 14, 8, 14]],
"p": [19, [4, 14, 4, -7, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3]],
"q": [19, [15, 14, 15, -7, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3]],
"r": [13, [4, 14, 4, 0, -1, -1, 4, 8, 5, 11, 7, 13, 9, 14, 12, 14]],
"s": [17, [14, 11, 13, 13, 10, 14, 7, 14, 4, 13, 3, 11, 4, 9, 6, 8, 11, 7, 13, 6, 14, 4, 14, 3, 13, 1, 10, 0, 7, 0, 4, 1, 3, 3]],
"t": [12, [5, 21, 5, 4, 6, 1, 8, 0, 10, 0, -1, -1, 2, 14, 9, 14]],
"u": [19, [4, 14, 4, 4, 5, 1, 7, 0, 10, 0, 12, 1, 15, 4, -1, -1, 15, 14, 15, 0]],
"v": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0]],
"w": [22, [3, 14, 7, 0, -1, -1, 11, 14, 7, 0, -1, -1, 11, 14, 15, 0, -1, -1, 19, 14, 15, 0]],
"x": [17, [3, 14, 14, 0, -1, -1, 14, 14, 3, 0]],
"y": [16, [2, 14, 8, 0, -1, -1, 14, 14, 8, 0, 6, -4, 4, -6, 2, -7, 1, -7]],
"z": [17, [14, 14, 3, 0, -1, -1, 3, 14, 14, 14, -1, -1, 3, 0, 14, 0]],
"{": [14, [9, 25, 7, 24, 6, 23, 5, 21, 5, 19, 6, 17, 7, 16, 8, 14, 8, 12, 6, 10, -1, -1, 7, 24, 6, 22, 6, 20, 7, 18, 8, 17, 9, 15, 9, 13, 8, 11, 4, 9, 8, 7, 9, 5, 9, 3, 8, 1, 7, 0, 6, -2, 6, -4, 7, -6, -1, -1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, -1, 5, -3, 6, -5, 7, -6, 9, -7]],
"|": [8, [4, 25, 4, -7]],
"}": [14, [5, 25, 7, 24, 8, 23, 9, 21, 9, 19, 8, 17, 7, 16, 6, 14, 6, 12, 8, 10, -1, -1, 7, 24, 8, 22, 8, 20, 7, 18, 6, 17, 5, 15, 5, 13, 6, 11, 10, 9, 6, 7, 5, 5, 5, 3, 6, 1, 7, 0, 8, -2, 8, -4, 7, -6, -1, -1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, -1, 9, -3, 8, -5, 7, -6, 5, -7]],
"~": [24, [3, 6, 3, 8, 4, 11, 6, 12, 8, 12, 10, 11, 14, 8, 16, 7, 18, 7, 20, 8, 21, 10, -1, -1, 3, 8, 4, 10, 6, 11, 8, 11, 10, 10, 14, 7, 16, 6, 18, 6, 20, 7, 21, 10, 21, 12]]
};
module.exports = function textVertices(text, left, baseline, scale) {
scale = scale || 1;
var strokes = [],
i, len, j, len2, glyph, x, y, prev;
for (i = 0, len = text.length; i < len; i++) {
glyph = simplexFont[text[i]];
if (!glyph) continue;
prev = null;
for (j = 0, len2 = glyph[1].length; j < len2; j += 2) {
if (glyph[1][j] === -1 && glyph[1][j + 1] === -1) {
prev = null;
} else {
x = left + glyph[1][j] * scale;
y = baseline - glyph[1][j + 1] * scale;
if (prev) {
strokes.push(prev.x, prev.y, x, y);
}
prev = {x: x, y: y};
}
}
left += glyph[0] * scale;
}
return strokes;
};
},{}],22:[function(require,module,exports){
'use strict';
/**
* mapboxgl is a A WebGL JavaScript interactive maps library that can render
* [Mapbox vector tiles](https://www.mapbox.com/blog/vector-tiles/).
*
* @module mapboxgl
* @summary WebGL JavaScript map library
*/
// jshint -W079
var mapboxgl = module.exports = {};
mapboxgl.Map = require('./ui/map');
mapboxgl.Navigation = require('./ui/control/navigation');
mapboxgl.Attribution = require('./ui/control/attribution');
mapboxgl.Popup = require('./ui/popup');
mapboxgl.GeoJSONSource = require('./source/geojson_source');
mapboxgl.VideoSource = require('./source/video_source');
mapboxgl.Style = require('./style/style');
mapboxgl.LatLng = require('./geo/lat_lng');
mapboxgl.LatLngBounds = require('./geo/lat_lng_bounds');
mapboxgl.Point = require('point-geometry');
mapboxgl.Evented = require('./util/evented');
mapboxgl.util = require('./util/util');
mapboxgl.supported = require('./util/browser').supported;
var ajax = require('./util/ajax');
mapboxgl.util.getJSON = ajax.getJSON;
mapboxgl.util.getArrayBuffer = ajax.getArrayBuffer;
var config = require('./util/config');
mapboxgl.config = config;
Object.defineProperty(mapboxgl, 'accessToken', {
get: function() { return config.ACCESS_TOKEN; },
set: function(token) { config.ACCESS_TOKEN = token; }
});
},{"./geo/lat_lng":18,"./geo/lat_lng_bounds":19,"./source/geojson_source":36,"./source/video_source":44,"./style/style":52,"./ui/control/attribution":75,"./ui/control/navigation":77,"./ui/map":81,"./ui/popup":82,"./util/ajax":84,"./util/browser":85,"./util/config":89,"./util/evented":90,"./util/util":96,"point-geometry":113}],23:[function(require,module,exports){
'use strict';
var mat3 = require('gl-matrix').mat3;
module.exports = drawBackground;
function drawBackground(painter, layer, posMatrix) {
var gl = painter.gl;
var color = layer.paint['background-color'];
var image = layer.paint['background-image'];
var opacity = layer.paint['background-opacity'];
var shader;
var imagePosA = image ? painter.spriteAtlas.getPosition(image.from, true) : null;
var imagePosB = image ? painter.spriteAtlas.getPosition(image.to, true) : null;
if (imagePosA && imagePosB) {
// Draw texture fill
shader = painter.patternShader;
gl.switchShader(shader, posMatrix);
gl.uniform1i(shader.u_image, 0);
gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl);
gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br);
gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl);
gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br);
gl.uniform1f(shader.u_opacity, opacity);
var transform = painter.transform;
var sizeA = imagePosA.size;
var sizeB = imagePosB.size;
var center = transform.locationCoordinate(transform.center);
var scale = 1 / Math.pow(2, transform.zoomFraction);
gl.uniform1f(shader.u_mix, image.t);
var matrixA = mat3.create();
mat3.scale(matrixA, matrixA, [
1 / (sizeA[0] * image.fromScale),
1 / (sizeA[1] * image.fromScale)
]);
mat3.translate(matrixA, matrixA, [
(center.column * transform.tileSize) % (sizeA[0] * image.fromScale),
(center.row * transform.tileSize) % (sizeA[1] * image.fromScale)
]);
mat3.rotate(matrixA, matrixA, -transform.angle);
mat3.scale(matrixA, matrixA, [
scale * transform.width / 2,
-scale * transform.height / 2
]);
var matrixB = mat3.create();
mat3.scale(matrixB, matrixB, [
1 / (sizeB[0] * image.toScale),
1 / (sizeB[1] * image.toScale)
]);
mat3.translate(matrixB, matrixB, [
(center.column * transform.tileSize) % (sizeB[0] * image.toScale),
(center.row * transform.tileSize) % (sizeB[1] * image.toScale)
]);
mat3.rotate(matrixB, matrixB, -transform.angle);
mat3.scale(matrixB, matrixB, [
scale * transform.width / 2,
-scale * transform.height / 2
]);
gl.uniformMatrix3fv(shader.u_patternmatrix_a, false, matrixA);
gl.uniformMatrix3fv(shader.u_patternmatrix_b, false, matrixB);
painter.spriteAtlas.bind(gl, true);
} else {
// Draw filling rectangle.
shader = painter.fillShader;
gl.switchShader(shader, posMatrix);
gl.uniform4fv(shader.u_color, color);
}
gl.disable(gl.STENCIL_TEST);
gl.bindBuffer(gl.ARRAY_BUFFER, painter.backgroundBuffer);
gl.vertexAttribPointer(shader.a_pos, painter.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.backgroundBuffer.itemCount);
gl.enable(gl.STENCIL_TEST);
gl.stencilMask(0x00);
gl.stencilFunc(gl.EQUAL, 0x80, 0x80);
}
},{"gl-matrix":104}],24:[function(require,module,exports){
'use strict';
module.exports = drawPlacementDebug;
function drawPlacementDebug(painter, layer, posMatrix, tile) {
var elementGroups = tile.elementGroups[layer.ref || layer.id].collisionBox;
if (!elementGroups) return;
var gl = painter.gl;
var buffer = tile.buffers.collisionBoxVertex;
var shader = painter.collisionBoxShader;
gl.enable(gl.STENCIL_TEST);
gl.switchShader(shader, posMatrix);
buffer.bind(gl, shader);
gl.lineWidth(3);
var stride = 12;
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, stride, 0);
gl.vertexAttribPointer(shader.a_extrude, 2, gl.SHORT, false, stride, 4);
gl.vertexAttribPointer(shader.a_data, 2, gl.UNSIGNED_BYTE, false, stride, 8);
gl.uniform1f(shader.u_scale, Math.pow(2, painter.transform.zoom - tile.coord.z));
gl.uniform1f(shader.u_zoom, painter.transform.zoom * 10);
gl.uniform1f(shader.u_maxzoom, (tile.coord.z + 1) * 10);
var begin = elementGroups.groups[0].vertexStartIndex;
var len = elementGroups.groups[0].vertexLength;
gl.drawArrays(gl.LINES, begin, len);
gl.disable(gl.STENCIL_TEST);
}
},{}],25:[function(require,module,exports){
'use strict';
var textVertices = require('../lib/debugtext');
var browser = require('../util/browser');
module.exports = drawDebug;
function drawDebug(painter, tile) {
var gl = painter.gl;
// Blend to the front, not the back.
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.switchShader(painter.debugShader, tile.posMatrix);
// draw bounding rectangle
gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugBuffer);
gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugBuffer.itemSize, gl.SHORT, false, 0, 0);
gl.uniform4f(painter.debugShader.u_color, 1, 0, 0, 1);
gl.lineWidth(4);
gl.drawArrays(gl.LINE_STRIP, 0, painter.debugBuffer.itemCount);
var vertices = textVertices(tile.coord.toString(), 50, 200, 5);
gl.bindBuffer(gl.ARRAY_BUFFER, painter.debugTextBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Int16Array(vertices), gl.STREAM_DRAW);
gl.vertexAttribPointer(painter.debugShader.a_pos, painter.debugTextBuffer.itemSize, gl.SHORT, false, 0, 0);
gl.lineWidth(8 * browser.devicePixelRatio);
gl.uniform4f(painter.debugShader.u_color, 1, 1, 1, 1);
gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize);
gl.lineWidth(2 * browser.devicePixelRatio);
gl.uniform4f(painter.debugShader.u_color, 0, 0, 0, 1);
gl.drawArrays(gl.LINES, 0, vertices.length / painter.debugTextBuffer.itemSize);
// Revert blending mode to blend to the back.
gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE);
}
},{"../lib/debugtext":21,"../util/browser":85}],26:[function(require,module,exports){
'use strict';
var browser = require('../util/browser');
var mat3 = require('gl-matrix').mat3;
module.exports = drawFill;
function drawFill(painter, layer, posMatrix, tile) {
// No data
if (!tile.buffers) return;
var elementGroups = tile.elementGroups[layer.ref || layer.id];
if (!elementGroups) return;
var gl = painter.gl;
var translatedPosMatrix = painter.translateMatrix(posMatrix, tile, layer.paint['fill-translate'], layer.paint['fill-translate-anchor']);
var color = layer.paint['fill-color'];
var vertex, elements, group, count;
// Draw the stencil mask.
// We're only drawing to the first seven bits (== support a maximum of
// 127 overlapping polygons in one place before we get rendering errors).
gl.stencilMask(0x3F);
gl.clear(gl.STENCIL_BUFFER_BIT);
// Draw front facing triangles. Wherever the 0x80 bit is 1, we are
// increasing the lower 7 bits by one if the triangle is a front-facing
// triangle. This means that all visible polygons should be in CCW
// orientation, while all holes (see below) are in CW orientation.
gl.stencilFunc(gl.NOTEQUAL, 0x80, 0x80);
// When we do a nonzero fill, we count the number of times a pixel is
// covered by a counterclockwise polygon, and subtract the number of
// times it is "uncovered" by a clockwise polygon.
gl.stencilOpSeparate(gl.FRONT, gl.INCR_WRAP, gl.KEEP, gl.KEEP);
gl.stencilOpSeparate(gl.BACK, gl.DECR_WRAP, gl.KEEP, gl.KEEP);
// When drawing a shape, we first draw all shapes to the stencil buffer
// and incrementing all areas where polygons are
gl.colorMask(false, false, false, false);
// Draw the actual triangle fan into the stencil buffer.
gl.switchShader(painter.fillShader, translatedPosMatrix);
// Draw all buffers
vertex = tile.buffers.fillVertex;
vertex.bind(gl);
elements = tile.buffers.fillElement;
elements.bind(gl);
var offset, elementOffset;
for (var i = 0; i < elementGroups.groups.length; i++) {
group = elementGroups.groups[i];
offset = group.vertexStartIndex * vertex.itemSize;
gl.vertexAttribPointer(painter.fillShader.a_pos, 2, gl.SHORT, false, 4, offset + 0);
count = group.elementLength * 3;
elementOffset = group.elementStartIndex * elements.itemSize;
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset);
}
// Now that we have the stencil mask in the stencil buffer, we can start
// writing to the color buffer.
gl.colorMask(true, true, true, true);
// From now on, we don't want to update the stencil buffer anymore.
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
gl.stencilMask(0x0);
var strokeColor = layer.paint['fill-outline-color'];
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (layer.paint['fill-antialias'] === true && !(layer.paint['fill-image'] && !strokeColor)) {
gl.switchShader(painter.outlineShader, translatedPosMatrix);
gl.lineWidth(2 * browser.devicePixelRatio);
if (strokeColor) {
// If we defined a different color for the fill outline, we are
// going to ignore the bits in 0x3F and just care about the global
// clipping mask.
gl.stencilFunc(gl.EQUAL, 0x80, 0x80);
} else {
// Otherwise, we only want to draw the antialiased parts that are
// *outside* the current shape. This is important in case the fill
// or stroke color is translucent. If we wouldn't clip to outside
// the current shape, some pixels from the outline stroke overlapped
// the (non-antialiased) fill.
gl.stencilFunc(gl.EQUAL, 0x80, 0xBF);
}
gl.uniform2f(painter.outlineShader.u_world, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.uniform4fv(painter.outlineShader.u_color, strokeColor ? strokeColor : color);
// Draw all buffers
vertex = tile.buffers.fillVertex;
elements = tile.buffers.outlineElement;
elements.bind(gl);
for (var k = 0; k < elementGroups.groups.length; k++) {
group = elementGroups.groups[k];
offset = group.vertexStartIndex * vertex.itemSize;
gl.vertexAttribPointer(painter.outlineShader.a_pos, 2, gl.SHORT, false, 4, offset + 0);
count = group.secondElementLength * 2;
elementOffset = group.secondElementStartIndex * elements.itemSize;
gl.drawElements(gl.LINES, count, gl.UNSIGNED_SHORT, elementOffset);
}
}
var image = layer.paint['fill-image'];
var opacity = layer.paint['fill-opacity'] || 1;
var shader;
if (image) {
// Draw texture fill
var imagePosA = painter.spriteAtlas.getPosition(image.from, true);
var imagePosB = painter.spriteAtlas.getPosition(image.to, true);
if (!imagePosA || !imagePosB) return;
shader = painter.patternShader;
gl.switchShader(shader, posMatrix);
gl.uniform1i(shader.u_image, 0);
gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl);
gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br);
gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl);
gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br);
gl.uniform1f(shader.u_opacity, opacity);
gl.uniform1f(shader.u_mix, image.t);
var factor = (tile.tileExtent / tile.tileSize) / Math.pow(2, painter.transform.tileZoom - tile.coord.z);
var matrixA = mat3.create();
mat3.scale(matrixA, matrixA, [
1 / (imagePosA.size[0] * factor * image.fromScale),
1 / (imagePosA.size[1] * factor * image.fromScale)
]);
var matrixB = mat3.create();
mat3.scale(matrixB, matrixB, [
1 / (imagePosB.size[0] * factor * image.toScale),
1 / (imagePosB.size[1] * factor * image.toScale)
]);
gl.uniformMatrix3fv(shader.u_patternmatrix_a, false, matrixA);
gl.uniformMatrix3fv(shader.u_patternmatrix_b, false, matrixB);
painter.spriteAtlas.bind(gl, true);
} else {
// Draw filling rectangle.
shader = painter.fillShader;
gl.switchShader(shader, posMatrix);
gl.uniform4fv(shader.u_color, color);
}
// Only draw regions that we marked
gl.stencilFunc(gl.NOTEQUAL, 0x0, 0x3F);
gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer);
gl.vertexAttribPointer(shader.a_pos, painter.tileExtentBuffer.itemSize, gl.SHORT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.tileExtentBuffer.itemCount);
gl.stencilMask(0x00);
gl.stencilFunc(gl.EQUAL, 0x80, 0x80);
}
},{"../util/browser":85,"gl-matrix":104}],27:[function(require,module,exports){
'use strict';
var browser = require('../util/browser');
var mat2 = require('gl-matrix').mat2;
/**
* Draw a line. Under the hood this will read elements from
* a tile, dash textures from a lineAtlas, and style properties from a layer.
* @param {Object} painter
* @param {Object} layer
* @param {Object} posMatrix
* @param {Tile} tile
* @returns {undefined} draws with the painter
*/
module.exports = function drawLine(painter, layer, posMatrix, tile) {
// No data
if (!tile.buffers) return;
var elementGroups = tile.elementGroups[layer.ref || layer.id];
if (!elementGroups) return;
var gl = painter.gl;
// don't draw zero-width lines
if (layer.paint['line-width'] <= 0) return;
// the distance over which the line edge fades out.
// Retina devices need a smaller distance to avoid aliasing.
var antialiasing = 1 / browser.devicePixelRatio;
var blur = layer.paint['line-blur'] + antialiasing;
var edgeWidth = layer.paint['line-width'] / 2;
var inset = -1;
var offset = 0;
var shift = 0;
if (layer.paint['line-gap-width'] > 0) {
inset = layer.paint['line-gap-width'] / 2 + antialiasing * 0.5;
edgeWidth = layer.paint['line-width'];
// shift outer lines half a pixel towards the middle to eliminate the crack
offset = inset - antialiasing / 2;
}
var outset = offset + edgeWidth + antialiasing / 2 + shift;
var color = layer.paint['line-color'];
var ratio = painter.transform.scale / (1 << tile.coord.z) / (tile.tileExtent / tile.tileSize);
var vtxMatrix = painter.translateMatrix(posMatrix, tile, layer.paint['line-translate'], layer.paint['line-translate-anchor']);
var tr = painter.transform;
var antialiasingMatrix = mat2.create();
mat2.scale(antialiasingMatrix, antialiasingMatrix, [1, Math.cos(tr._pitch)]);
mat2.rotate(antialiasingMatrix, antialiasingMatrix, painter.transform.angle);
// calculate how much longer the real world distance is at the top of the screen
// than at the middle of the screen.
var topedgelength = Math.sqrt(tr.height * tr.height / 4 * (1 + tr.altitude * tr.altitude));
var x = tr.height / 2 * Math.tan(tr._pitch);
var extra = (topedgelength + x) / topedgelength - 1;
// how much the tile is overscaled by
var overscaling = tile.tileSize / painter.transform.tileSize;
var shader;
var dasharray = layer.paint['line-dasharray'];
var image = layer.paint['line-image'];
if (dasharray) {
shader = painter.linesdfpatternShader;
gl.switchShader(shader, vtxMatrix, tile.exMatrix);
gl.uniform2fv(shader.u_linewidth, [ outset, inset ]);
gl.uniform1f(shader.u_ratio, ratio);
gl.uniform1f(shader.u_blur, blur);
gl.uniform4fv(shader.u_color, color);
var posA = painter.lineAtlas.getDash(dasharray.from, layer.layout['line-cap'] === 'round');
var posB = painter.lineAtlas.getDash(dasharray.to, layer.layout['line-cap'] === 'round');
painter.lineAtlas.bind(gl);
var patternratio = Math.pow(2, Math.floor(Math.log(painter.transform.scale) / Math.LN2) - tile.coord.z) / 8 * overscaling;
var scaleA = [patternratio / posA.width / dasharray.fromScale, -posA.height / 2];
var gammaA = painter.lineAtlas.width / (dasharray.fromScale * posA.width * 256 * browser.devicePixelRatio) / 2;
var scaleB = [patternratio / posB.width / dasharray.toScale, -posB.height / 2];
var gammaB = painter.lineAtlas.width / (dasharray.toScale * posB.width * 256 * browser.devicePixelRatio) / 2;
gl.uniform2fv(shader.u_patternscale_a, scaleA);
gl.uniform1f(shader.u_tex_y_a, posA.y);
gl.uniform2fv(shader.u_patternscale_b, scaleB);
gl.uniform1f(shader.u_tex_y_b, posB.y);
gl.uniform1i(shader.u_image, 0);
gl.uniform1f(shader.u_sdfgamma, Math.max(gammaA, gammaB));
gl.uniform1f(shader.u_mix, dasharray.t);
} else if (image) {
var imagePosA = painter.spriteAtlas.getPosition(image.from, true);
var imagePosB = painter.spriteAtlas.getPosition(image.to, true);
if (!imagePosA || !imagePosB) return;
var factor = tile.tileExtent / tile.tileSize / Math.pow(2, painter.transform.tileZoom - tile.coord.z) * overscaling;
painter.spriteAtlas.bind(gl, true);
shader = painter.linepatternShader;
gl.switchShader(shader, vtxMatrix, tile.exMatrix);
gl.uniform2fv(shader.u_linewidth, [ outset, inset ]);
gl.uniform1f(shader.u_ratio, ratio);
gl.uniform1f(shader.u_blur, blur);
gl.uniform2fv(shader.u_pattern_size_a, [imagePosA.size[0] * factor * image.fromScale, imagePosB.size[1] ]);
gl.uniform2fv(shader.u_pattern_size_b, [imagePosB.size[0] * factor * image.toScale, imagePosB.size[1] ]);
gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl);
gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br);
gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl);
gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br);
gl.uniform1f(shader.u_fade, image.t);
gl.uniform1f(shader.u_opacity, layer.paint['line-opacity']);
} else {
shader = painter.lineShader;
gl.switchShader(shader, vtxMatrix, tile.exMatrix);
gl.uniform2fv(shader.u_linewidth, [ outset, inset ]);
gl.uniform1f(shader.u_ratio, ratio);
gl.uniform1f(shader.u_blur, blur);
gl.uniform1f(shader.u_extra, extra);
gl.uniformMatrix2fv(shader.u_antialiasingmatrix, false, antialiasingMatrix);
gl.uniform4fv(shader.u_color, color);
}
var vertex = tile.buffers.lineVertex;
vertex.bind(gl);
var element = tile.buffers.lineElement;
element.bind(gl);
for (var i = 0; i < elementGroups.groups.length; i++) {
var group = elementGroups.groups[i];
var vtxOffset = group.vertexStartIndex * vertex.itemSize;
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, vtxOffset + 0);
gl.vertexAttribPointer(shader.a_data, 4, gl.BYTE, false, 8, vtxOffset + 4);
var count = group.elementLength * 3;
var elementOffset = group.elementStartIndex * element.itemSize;
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset);
}
};
},{"../util/browser":85,"gl-matrix":104}],28:[function(require,module,exports){
'use strict';
var util = require('../util/util');
module.exports = drawRaster;
function drawRaster(painter, layer, posMatrix, tile) {
var gl = painter.gl;
gl.disable(gl.STENCIL_TEST);
var shader = painter.rasterShader;
gl.switchShader(shader, posMatrix);
// color parameters
gl.uniform1f(shader.u_brightness_low, layer.paint['raster-brightness-min']);
gl.uniform1f(shader.u_brightness_high, layer.paint['raster-brightness-max']);
gl.uniform1f(shader.u_saturation_factor, saturationFactor(layer.paint['raster-saturation']));
gl.uniform1f(shader.u_contrast_factor, contrastFactor(layer.paint['raster-contrast']));
gl.uniform3fv(shader.u_spin_weights, spinWeights(layer.paint['raster-hue-rotate']));
var parentTile = tile.source && tile.source._pyramid.findLoadedParent(tile.coord, 0, {}),
opacities = getOpacities(tile, parentTile, layer, painter.transform);
var parentScaleBy, parentTL;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
if (parentTile) {
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, parentTile.texture);
parentScaleBy = Math.pow(2, parentTile.coord.z - tile.coord.z);
parentTL = [tile.coord.x * parentScaleBy % 1, tile.coord.y * parentScaleBy % 1];
} else {
opacities[1] = 0;
}
// cross-fade parameters
gl.uniform2fv(shader.u_tl_parent, parentTL || [0, 0]);
gl.uniform1f(shader.u_scale_parent, parentScaleBy || 1);
gl.uniform1f(shader.u_buffer_scale, 1);
gl.uniform1f(shader.u_opacity0, opacities[0]);
gl.uniform1f(shader.u_opacity1, opacities[1]);
gl.uniform1i(shader.u_image0, 0);
gl.uniform1i(shader.u_image1, 1);
gl.bindBuffer(gl.ARRAY_BUFFER, tile.boundsBuffer || painter.tileExtentBuffer);
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, 0);
gl.vertexAttribPointer(shader.a_texture_pos, 2, gl.SHORT, false, 8, 4);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.enable(gl.STENCIL_TEST);
}
function spinWeights(angle) {
angle *= Math.PI / 180;
var s = Math.sin(angle);
var c = Math.cos(angle);
return [
(2 * c + 1) / 3,
(-Math.sqrt(3) * s - c + 1) / 3,
(Math.sqrt(3) * s - c + 1) / 3
];
}
function contrastFactor(contrast) {
return contrast > 0 ?
1 / (1 - contrast) :
1 + contrast;
}
function saturationFactor(saturation) {
return saturation > 0 ?
1 - 1 / (1.001 - saturation) :
-saturation;
}
function getOpacities(tile, parentTile, layer, transform) {
if (!tile.source) return [1, 0];
var now = new Date().getTime();
var fadeDuration = layer.paint['raster-fade-duration'];
var sinceTile = (now - tile.timeAdded) / fadeDuration;
var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1;
var idealZ = tile.source._pyramid.coveringZoomLevel(transform);
var parentFurther = parentTile ? Math.abs(parentTile.coord.z - idealZ) > Math.abs(tile.coord.z - idealZ) : false;
var opacity = [];
if (!parentTile || parentFurther) {
// if no parent or parent is older
opacity[0] = util.clamp(sinceTile, 0, 1);
opacity[1] = 1 - opacity[0];
} else {
// parent is younger, zooming out
opacity[0] = util.clamp(1 - sinceParent, 0, 1);
opacity[1] = 1 - opacity[0];
}
var op = layer.paint['raster-opacity'];
opacity[0] *= op;
opacity[1] *= op;
return opacity;
}
},{"../util/util":96}],29:[function(require,module,exports){
'use strict';
var browser = require('../util/browser');
var mat4 = require('gl-matrix').mat4;
var drawCollisionDebug = require('./draw_collision_debug');
module.exports = drawSymbols;
function drawSymbols(painter, layer, posMatrix, tile) {
// No data
if (!tile.buffers) return;
var elementGroups = tile.elementGroups[layer.ref || layer.id];
if (!elementGroups) return;
var drawAcrossEdges = !(layer.layout['text-allow-overlap'] || layer.layout['icon-allow-overlap'] ||
layer.layout['text-ignore-placement'] || layer.layout['icon-ignore-placement']);
var gl = painter.gl;
if (drawAcrossEdges) {
// Disable the stencil test so that labels aren't clipped to tile boundaries.
//
// Layers with features that may be drawn overlapping aren't clipped. These
// layers are sorted in the y direction, and to draw the correct ordering near
// tile edges the icons are included in both tiles and clipped when drawing.
gl.disable(gl.STENCIL_TEST);
}
if (elementGroups.text.groups.length) {
drawSymbol(painter, layer, posMatrix, tile, elementGroups.text, 'text', true);
}
if (elementGroups.icon.groups.length) {
drawSymbol(painter, layer, posMatrix, tile, elementGroups.icon, 'icon', elementGroups.sdfIcons);
}
drawCollisionDebug(painter, layer, posMatrix, tile);
if (drawAcrossEdges) {
gl.enable(gl.STENCIL_TEST);
}
}
var defaultSizes = {
icon: 1,
text: 24
};
function drawSymbol(painter, layer, posMatrix, tile, elementGroups, prefix, sdf) {
var gl = painter.gl;
posMatrix = painter.translateMatrix(posMatrix, tile, layer.paint[prefix + '-translate'], layer.paint[prefix + '-translate-anchor']);
var tr = painter.transform;
var alignedWithMap = layer.layout[prefix + '-rotation-alignment'] === 'map';
var skewed = alignedWithMap;
var exMatrix, s, gammaScale;
if (skewed) {
exMatrix = mat4.create();
s = tile.tileExtent / tile.tileSize / Math.pow(2, painter.transform.zoom - tile.coord.z);
gammaScale = 1 / Math.cos(tr._pitch);
} else {
exMatrix = mat4.clone(tile.exMatrix);
s = painter.transform.altitude;
gammaScale = 1;
}
mat4.scale(exMatrix, exMatrix, [s, s, 1]);
// If layer.paint.size > layer.layout[prefix + '-max-size'] then labels may collide
var fontSize = layer.paint[prefix + '-size'];
var fontScale = fontSize / defaultSizes[prefix];
mat4.scale(exMatrix, exMatrix, [ fontScale, fontScale, 1 ]);
// calculate how much longer the real world distance is at the top of the screen
// than at the middle of the screen.
var topedgelength = Math.sqrt(tr.height * tr.height / 4 * (1 + tr.altitude * tr.altitude));
var x = tr.height / 2 * Math.tan(tr._pitch);
var extra = (topedgelength + x) / topedgelength - 1;
var text = prefix === 'text';
var shader, vertex, elements, texsize;
if (!text && !painter.style.sprite.loaded())
return;
gl.activeTexture(gl.TEXTURE0);
if (sdf) {
shader = painter.sdfShader;
} else {
shader = painter.iconShader;
}
if (text) {
painter.glyphAtlas.updateTexture(gl);
vertex = tile.buffers.glyphVertex;
elements = tile.buffers.glyphElement;
texsize = [painter.glyphAtlas.width / 4, painter.glyphAtlas.height / 4];
} else {
painter.spriteAtlas.bind(gl, alignedWithMap || painter.options.rotating ||
painter.options.zooming || fontScale !== 1 || sdf || painter.transform.pitch);
vertex = tile.buffers.iconVertex;
elements = tile.buffers.iconElement;
texsize = [painter.spriteAtlas.width / 4, painter.spriteAtlas.height / 4];
}
gl.switchShader(shader, posMatrix, exMatrix);
gl.uniform1i(shader.u_texture, 0);
gl.uniform2fv(shader.u_texsize, texsize);
gl.uniform1i(shader.u_skewed, skewed);
gl.uniform1f(shader.u_extra, extra);
// adjust min/max zooms for variable font sies
var zoomAdjust = Math.log(fontSize / layer.layout[prefix + '-max-size']) / Math.LN2 || 0;
gl.uniform1f(shader.u_zoom, (painter.transform.zoom - zoomAdjust) * 10); // current zoom level
var f = painter.frameHistory.getFadeProperties(300);
gl.uniform1f(shader.u_fadedist, f.fadedist * 10);
gl.uniform1f(shader.u_minfadezoom, Math.floor(f.minfadezoom * 10));
gl.uniform1f(shader.u_maxfadezoom, Math.floor(f.maxfadezoom * 10));
gl.uniform1f(shader.u_fadezoom, (painter.transform.zoom + f.bump) * 10);
var group, offset, count, elementOffset;
elements.bind(gl);
if (sdf) {
var sdfPx = 8;
var blurOffset = 1.19;
var haloOffset = 6;
var gamma = 0.105 * defaultSizes[prefix] / fontSize / browser.devicePixelRatio;
gl.uniform1f(shader.u_gamma, gamma * gammaScale);
gl.uniform4fv(shader.u_color, layer.paint[prefix + '-color']);
gl.uniform1f(shader.u_buffer, (256 - 64) / 256);
for (var i = 0; i < elementGroups.groups.length; i++) {
group = elementGroups.groups[i];
offset = group.vertexStartIndex * vertex.itemSize;
vertex.bind(gl, shader, offset);
count = group.elementLength * 3;
elementOffset = group.elementStartIndex * elements.itemSize;
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset);
}
if (layer.paint[prefix + '-halo-color']) {
// Draw halo underneath the text.
gl.uniform1f(shader.u_gamma, (layer.paint[prefix + '-halo-blur'] * blurOffset / fontScale / sdfPx + gamma) * gammaScale);
gl.uniform4fv(shader.u_color, layer.paint[prefix + '-halo-color']);
gl.uniform1f(shader.u_buffer, (haloOffset - layer.paint[prefix + '-halo-width'] / fontScale) / sdfPx);
for (var j = 0; j < elementGroups.groups.length; j++) {
group = elementGroups.groups[j];
offset = group.vertexStartIndex * vertex.itemSize;
vertex.bind(gl, shader, offset);
count = group.elementLength * 3;
elementOffset = group.elementStartIndex * elements.itemSize;
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset);
}
}
} else {
gl.uniform1f(shader.u_opacity, layer.paint['icon-opacity']);
for (var k = 0; k < elementGroups.groups.length; k++) {
group = elementGroups.groups[k];
offset = group.vertexStartIndex * vertex.itemSize;
vertex.bind(gl, shader, offset);
count = group.elementLength * 3;
elementOffset = group.elementStartIndex * elements.itemSize;
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, elementOffset);
}
}
}
},{"../util/browser":85,"./draw_collision_debug":24,"gl-matrix":104}],30:[function(require,module,exports){
'use strict';
var browser = require('../util/browser');
var mat4 = require('gl-matrix').mat4;
module.exports = drawVertices;
function drawVertices(painter, layer, posMatrix, tile) {
var gl = painter.gl;
if (!tile || !tile.buffers) return;
var elementGroups = tile.elementGroups[layer.ref || layer.id];
if (!elementGroups) return;
// Blend to the front, not the back.
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
// Draw all buffers
if (layer.type === 'fill') {
drawPoints(tile.buffers.fillVertex, elementGroups.groups, posMatrix, 4);
} else if (layer.type === 'symbol') {
drawPoints(tile.buffers.iconVertex, elementGroups.icon.groups, posMatrix, 16);
drawPoints(tile.buffers.glyphVertex, elementGroups.text.groups, posMatrix, 16);
} else if (layer.type === 'line') {
var newPosMatrix = mat4.clone(posMatrix);
mat4.scale(newPosMatrix, newPosMatrix, [0.5, 0.5, 1]);
drawPoints(tile.buffers.lineVertex, elementGroups.groups, newPosMatrix, 8);
}
function drawPoints(vertex, groups, matrix, stride) {
gl.switchShader(painter.dotShader, matrix);
gl.uniform1f(painter.dotShader.u_size, 4 * browser.devicePixelRatio);
gl.uniform1f(painter.dotShader.u_blur, 0.25);
gl.uniform4fv(painter.dotShader.u_color, [0.1, 0, 0, 0.1]);
vertex.bind(gl, painter.dotShader, 0);
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
var begin = group.vertexStartIndex;
var count = group.vertexLength;
gl.vertexAttribPointer(painter.dotShader.a_pos, 2, gl.SHORT, false, stride, 0);
gl.drawArrays(gl.POINTS, begin, count);
}
}
// Revert blending mode to blend to the back.
gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE);
}
},{"../util/browser":85,"gl-matrix":104}],31:[function(require,module,exports){
'use strict';
module.exports = FrameHistory;
function FrameHistory() {
this.frameHistory = [];
}
FrameHistory.prototype.getFadeProperties = function(duration) {
if (duration === undefined) duration = 300;
var currentTime = (new Date()).getTime();
// Remove frames until only one is outside the duration, or until there are only three
while (this.frameHistory.length > 3 && this.frameHistory[1].time + duration < currentTime) {
this.frameHistory.shift();
}
if (this.frameHistory[1].time + duration < currentTime) {
this.frameHistory[0].z = this.frameHistory[1].z;
}
var frameLen = this.frameHistory.length;
if (frameLen < 3) console.warn('there should never be less than three frames in the history');
// Find the range of zoom levels we want to fade between
var startingZ = this.frameHistory[0].z,
lastFrame = this.frameHistory[frameLen - 1],
endingZ = lastFrame.z,
lowZ = Math.min(startingZ, endingZ),
highZ = Math.max(startingZ, endingZ);
// Calculate the speed of zooming, and how far it would zoom in terms of zoom levels in one duration
var zoomDiff = lastFrame.z - this.frameHistory[1].z,
timeDiff = lastFrame.time - this.frameHistory[1].time;
var fadedist = zoomDiff / (timeDiff / duration);
if (isNaN(fadedist)) console.warn('fadedist should never be NaN');
// At end of a zoom when the zoom stops changing continue pretending to zoom at that speed
// bump is how much farther it would have been if it had continued zooming at the same rate
var bump = (currentTime - lastFrame.time) / duration * fadedist;
return {
fadedist: fadedist,
minfadezoom: lowZ,
maxfadezoom: highZ,
bump: bump
};
};
// Record frame history that will be used to calculate fading params
FrameHistory.prototype.record = function(zoom) {
var currentTime = (new Date()).getTime();
// first frame ever
if (!this.frameHistory.length) {
this.frameHistory.push({time: 0, z: zoom }, {time: 0, z: zoom });
}
if (this.frameHistory.length === 2 || this.frameHistory[this.frameHistory.length - 1].z !== zoom) {
this.frameHistory.push({
time: currentTime,
z: zoom
});
}
};
},{}],32:[function(require,module,exports){
'use strict';
var shaders = require('./shaders');
var util = require('../util/util');
exports.extend = function(context) {
var origLineWidth = context.lineWidth,
lineWidthRange = context.getParameter(context.ALIASED_LINE_WIDTH_RANGE);
context.lineWidth = function(width) {
origLineWidth.call(context, util.clamp(width, lineWidthRange[0], lineWidthRange[1]));
};
context.getShader = function(name, type) {
var kind = type === this.FRAGMENT_SHADER ? 'fragment' : 'vertex';
if (!shaders[name] || !shaders[name][kind]) {
throw new Error("Could not find shader " + name);
}
var shader = this.createShader(type);
this.shaderSource(shader, shaders[name][kind]);
this.compileShader(shader);
if (!this.getShaderParameter(shader, this.COMPILE_STATUS)) {
throw new Error(this.getShaderInfoLog(shader));
}
return shader;
};
context.initializeShader = function(name, attributes, uniforms) {
var shader = {
program: this.createProgram(),
fragment: this.getShader(name, this.FRAGMENT_SHADER),
vertex: this.getShader(name, this.VERTEX_SHADER),
attributes: []
};
this.attachShader(shader.program, shader.vertex);
this.attachShader(shader.program, shader.fragment);
this.linkProgram(shader.program);
if (!this.getProgramParameter(shader.program, this.LINK_STATUS)) {
console.error(this.getProgramInfoLog(shader.program));
} else {
for (var i = 0; i < attributes.length; i++) {
shader[attributes[i]] = this.getAttribLocation(shader.program, attributes[i]);
shader.attributes.push(shader[attributes[i]]);
}
for (var k = 0; k < uniforms.length; k++) {
shader[uniforms[k]] = this.getUniformLocation(shader.program, uniforms[k]);
}
}
return shader;
};
// Switches to a different shader program.
context.switchShader = function(shader, posMatrix, exMatrix) {
if (!posMatrix) {
console.trace('posMatrix does not have required argument');
}
if (this.currentShader !== shader) {
this.useProgram(shader.program);
// Disable all attributes from the existing shader that aren't used in
// the new shader. Note: attribute indices are *not* program specific!
var enabled = this.currentShader ? this.currentShader.attributes : [];
var required = shader.attributes;
for (var i = 0; i < enabled.length; i++) {
if (required.indexOf(enabled[i]) < 0) {
this.disableVertexAttribArray(enabled[i]);
}
}
// Enable all attributes for the new shader.
for (var j = 0; j < required.length; j++) {
if (enabled.indexOf(required[j]) < 0) {
this.enableVertexAttribArray(required[j]);
}
}
this.currentShader = shader;
}
// Update the matrices if necessary. Note: This relies on object identity!
// This means changing the matrix values without the actual matrix object
// will FAIL to update the matrix properly.
if (shader.posMatrix !== posMatrix) {
this.uniformMatrix4fv(shader.u_matrix, false, posMatrix);
shader.posMatrix = posMatrix;
}
if (exMatrix && shader.exMatrix !== exMatrix && shader.u_exmatrix) {
this.uniformMatrix4fv(shader.u_exmatrix, false, exMatrix);
shader.exMatrix = exMatrix;
}
};
return context;
};
},{"../util/util":96,"./shaders":35}],33:[function(require,module,exports){
'use strict';
module.exports = LineAtlas;
/**
* Much like a GlyphAtlas, a LineAtlas lets us reuse rendered dashed lines
* by writing many of them to a texture and then fetching their positions
* using .getDash.
*
* @param {number} width
* @param {number} height
* @private
*/
function LineAtlas(width, height) {
this.width = width;
this.height = height;
this.nextRow = 0;
this.bytes = 4;
this.data = new Uint8Array(this.width * this.height * this.bytes);
this.positions = {};
}
LineAtlas.prototype.setSprite = function(sprite) {
this.sprite = sprite;
};
/**
* Get or create a dash line pattern.
*
* @param {Array<number>} dasharray
* @param {boolean} round whether to add circle caps in between dash segments
* @returns {Object} position of dash texture in { y, height, width }
* @private
*/
LineAtlas.prototype.getDash = function(dasharray, round) {
var key = dasharray.join(",") + round;
if (!this.positions[key]) {
this.positions[key] = this.addDash(dasharray, round);
}
return this.positions[key];
};
LineAtlas.prototype.addDash = function(dasharray, round) {
var n = round ? 7 : 0;
var height = 2 * n + 1;
var offset = 128;
if (this.nextRow + height > this.height) {
console.warn('LineAtlas out of space');
return null;
}
var length = 0;
for (var i = 0; i < dasharray.length; i++) {
length += dasharray[i];
}
var stretch = this.width / length;
var halfWidth = stretch / 2;
// If dasharray has an odd length, both the first and last parts
// are dashes and should be joined seamlessly.
var oddLength = dasharray.length % 2 === 1;
for (var y = -n; y <= n; y++) {
var row = this.nextRow + n + y;
var index = this.width * row;
var left = oddLength ? -dasharray[dasharray.length - 1] : 0;
var right = dasharray[0];
var partIndex = 1;
for (var x = 0; x < this.width; x++) {
while (right < x / stretch) {
left = right;
right = right + dasharray[partIndex];
if (oddLength && partIndex === dasharray.length - 1) {
right += dasharray[0];
}
partIndex++;
}
var distLeft = Math.abs(x - left * stretch);
var distRight = Math.abs(x - right * stretch);
var dist = Math.min(distLeft, distRight);
var inside = (partIndex % 2) === 1;
var signedDistance;
if (round) {
// Add circle caps
var distMiddle = n ? y / n * (halfWidth + 1) : 0;
if (inside) {
var distEdge = halfWidth - Math.abs(distMiddle);
signedDistance = Math.sqrt(dist * dist + distEdge * distEdge);
} else {
signedDistance = halfWidth - Math.sqrt(dist * dist + distMiddle * distMiddle);
}
} else {
signedDistance = (inside ? 1 : -1) * dist;
}
this.data[3 + (index + x) * 4] = Math.max(0, Math.min(255, signedDistance + offset));
}
}
var pos = {
y: (this.nextRow + n + 0.5) / this.height,
height: 2 * n / this.height,
width: length
};
this.nextRow += height;
this.dirty = true;
return pos;
};
LineAtlas.prototype.bind = function(gl) {
if (!this.texture) {
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.data);
} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);
if (this.dirty) {
this.dirty = false;
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, this.data);
}
}
};
LineAtlas.prototype.debug = function() {
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.style.position = 'absolute';
canvas.style.top = 0;
canvas.style.left = 0;
canvas.style.background = '#ff0';
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
var data = ctx.getImageData(0, 0, this.width, this.height);
for (var i = 0; i < this.data.length; i++) {
if (this.sdf) {
var k = i * 4;
data.data[k] = data.data[k + 1] = data.data[k + 2] = 0;
data.data[k + 3] = this.data[i];
} else {
data.data[i] = this.data[i];
}
}
ctx.putImageData(data, 0, 0);
};
},{}],34:[function(require,module,exports){
'use strict';
var glutil = require('./gl_util');
var browser = require('../util/browser');
var mat4 = require('gl-matrix').mat4;
var FrameHistory = require('./frame_history');
/*
* Initialize a new painter object.
*
* @param {Canvas} gl an experimental-webgl drawing context
*/
module.exports = Painter;
function Painter(gl, transform) {
this.gl = glutil.extend(gl);
this.transform = transform;
this.reusableTextures = {};
this.preFbos = {};
this.frameHistory = new FrameHistory();
this.setup();
}
/*
* Update the GL viewport, projection matrix, and transforms to compensate
* for a new width and height value.
*/
Painter.prototype.resize = function(width, height) {
var gl = this.gl;
this.width = width * browser.devicePixelRatio;
this.height = height * browser.devicePixelRatio;
gl.viewport(0, 0, this.width, this.height);
};
Painter.prototype.setup = function() {
var gl = this.gl;
gl.verbose = true;
// We are blending the new pixels *behind* the existing pixels. That way we can
// draw front-to-back and use then stencil buffer to cull opaque pixels early.
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE);
gl.enable(gl.STENCIL_TEST);
// Initialize shaders
this.debugShader = gl.initializeShader('debug',
['a_pos'],
['u_matrix', 'u_pointsize', 'u_color']);
this.gaussianShader = gl.initializeShader('gaussian',
['a_pos'],
['u_matrix', 'u_image', 'u_offset']);
this.rasterShader = gl.initializeShader('raster',
['a_pos', 'a_texture_pos'],
['u_matrix', 'u_brightness_low', 'u_brightness_high', 'u_saturation_factor', 'u_spin_weights', 'u_contrast_factor', 'u_opacity0', 'u_opacity1', 'u_image0', 'u_image1', 'u_tl_parent', 'u_scale_parent', 'u_buffer_scale']);
this.lineShader = gl.initializeShader('line',
['a_pos', 'a_data'],
['u_matrix', 'u_linewidth', 'u_color', 'u_ratio', 'u_blur', 'u_extra', 'u_antialiasingmatrix']);
this.linepatternShader = gl.initializeShader('linepattern',
['a_pos', 'a_data'],
['u_matrix', 'u_exmatrix', 'u_linewidth', 'u_ratio', 'u_pattern_size_a', 'u_pattern_size_b', 'u_pattern_tl_a', 'u_pattern_br_a', 'u_pattern_tl_b', 'u_pattern_br_b', 'u_blur', 'u_fade', 'u_opacity']);
this.linesdfpatternShader = gl.initializeShader('linesdfpattern',
['a_pos', 'a_data'],
['u_matrix', 'u_exmatrix', 'u_linewidth', 'u_color', 'u_ratio', 'u_blur', 'u_patternscale_a', 'u_tex_y_a', 'u_patternscale_b', 'u_tex_y_b', 'u_image', 'u_sdfgamma', 'u_mix']);
this.dotShader = gl.initializeShader('dot',
['a_pos'],
['u_matrix', 'u_size', 'u_color', 'u_blur']);
this.sdfShader = gl.initializeShader('sdf',
['a_pos', 'a_offset', 'a_data1', 'a_data2'],
['u_matrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_color', 'u_gamma', 'u_buffer', 'u_zoom', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom', 'u_skewed', 'u_extra']);
this.iconShader = gl.initializeShader('icon',
['a_pos', 'a_offset', 'a_data1', 'a_data2'],
['u_matrix', 'u_exmatrix', 'u_texture', 'u_texsize', 'u_zoom', 'u_fadedist', 'u_minfadezoom', 'u_maxfadezoom', 'u_fadezoom', 'u_opacity', 'u_skewed', 'u_extra']);
this.outlineShader = gl.initializeShader('outline',
['a_pos'],
['u_matrix', 'u_color', 'u_world']
);
this.patternShader = gl.initializeShader('pattern',
['a_pos'],
['u_matrix', 'u_pattern_tl_a', 'u_pattern_br_a', 'u_pattern_tl_b', 'u_pattern_br_b', 'u_mix', 'u_patternmatrix_a', 'u_patternmatrix_b', 'u_opacity', 'u_image']
);
this.fillShader = gl.initializeShader('fill',
['a_pos'],
['u_matrix', 'u_color']
);
this.collisionBoxShader = gl.initializeShader('collisionbox',
['a_pos', 'a_extrude', 'a_data'],
['u_matrix', 'u_scale', 'u_zoom', 'u_maxzoom']
);
this.identityMatrix = mat4.create();
// The backgroundBuffer is used when drawing to the full *canvas*
this.backgroundBuffer = gl.createBuffer();
this.backgroundBuffer.itemSize = 2;
this.backgroundBuffer.itemCount = 4;
gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
this.setExtent(4096);
// The debugTextBuffer is used to draw tile IDs for debugging
this.debugTextBuffer = gl.createBuffer();
this.debugTextBuffer.itemSize = 2;
};
/**
* Rebind the necessary buffers to render at a different extent than
* the current one. No-ops if the extent is not changing.
*
* @param {number} newExtent
* @example
* this.setExtent(4096);
*/
Painter.prototype.setExtent = function(newExtent) {
if (!newExtent || newExtent === this.tileExtent) return;
this.tileExtent = newExtent;
var gl = this.gl;
// The tileExtentBuffer is used when drawing to a full *tile*
this.tileExtentBuffer = gl.createBuffer();
this.tileExtentBuffer.itemSize = 4;
this.tileExtentBuffer.itemCount = 4;
gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Int16Array([
// tile coord x, tile coord y, texture coord x, texture coord y
0, 0, 0, 0,
this.tileExtent, 0, 32767, 0,
0, this.tileExtent, 0, 32767,
this.tileExtent, this.tileExtent, 32767, 32767
]),
gl.STATIC_DRAW);
// The debugBuffer is used to draw tile outlines for debugging
this.debugBuffer = gl.createBuffer();
this.debugBuffer.itemSize = 2;
this.debugBuffer.itemCount = 5;
gl.bindBuffer(gl.ARRAY_BUFFER, this.debugBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Int16Array([
0, 0, this.tileExtent - 1, 0, this.tileExtent - 1, this.tileExtent - 1, 0, this.tileExtent - 1, 0, 0]),
gl.STATIC_DRAW);
};
/*
* Reset the color buffers of the drawing canvas.
*/
Painter.prototype.clearColor = function() {
var gl = this.gl;
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
};
/*
* Reset the drawing canvas by clearing the stencil buffer so that we can draw
* new tiles at the same location, while retaining previously drawn pixels.
*/
Painter.prototype.clearStencil = function() {
var gl = this.gl;
gl.clearStencil(0x0);
gl.stencilMask(0xFF);
gl.clear(gl.STENCIL_BUFFER_BIT);
};
Painter.prototype.drawClippingMask = function(tile) {
var gl = this.gl;
gl.switchShader(this.fillShader, tile.posMatrix);
gl.colorMask(false, false, false, false);
// Clear the entire stencil buffer, except for the 7th bit, which stores
// the global clipping mask that allows us to avoid drawing in regions of
// tiles we've already painted in.
gl.clearStencil(0x0);
gl.stencilMask(0xBF);
gl.clear(gl.STENCIL_BUFFER_BIT);
// The stencil test will fail always, meaning we set all pixels covered
// by this geometry to 0x80. We use the highest bit 0x80 to mark the regions
// we want to draw in. All pixels that have this bit *not* set will never be
// drawn in.
gl.stencilFunc(gl.EQUAL, 0xC0, 0x40);
gl.stencilMask(0xC0);
gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
// Draw the clipping mask
gl.bindBuffer(gl.ARRAY_BUFFER, this.tileExtentBuffer);
gl.vertexAttribPointer(this.fillShader.a_pos, this.tileExtentBuffer.itemSize, gl.SHORT, false, 8, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.tileExtentBuffer.itemCount);
gl.stencilFunc(gl.EQUAL, 0x80, 0x80);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
gl.stencilMask(0x00);
gl.colorMask(true, true, true, true);
};
// Overridden by headless tests.
Painter.prototype.prepareBuffers = function() {};
Painter.prototype.bindDefaultFramebuffer = function() {
var gl = this.gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
};
var draw = {
symbol: require('./draw_symbol'),
line: require('./draw_line'),
fill: require('./draw_fill'),
raster: require('./draw_raster'),
background: require('./draw_background'),
debug: require('./draw_debug'),
vertices: require('./draw_vertices')
};
Painter.prototype.render = function(style, options) {
this.style = style;
this.options = options;
this.lineAtlas = style.lineAtlas;
this.spriteAtlas = style.spriteAtlas;
this.spriteAtlas.setSprite(style.sprite);
this.glyphAtlas = style.glyphAtlas;
this.glyphAtlas.bind(this.gl);
this.frameHistory.record(this.transform.zoom);
this.prepareBuffers();
this.clearColor();
for (var i = style._groups.length - 1; i >= 0; i--) {
var group = style._groups[i];
var source = style.sources[group.source];
if (source) {
this.clearStencil();
source.render(group, this);
} else if (group.source === undefined) {
this.drawLayers(group, this.identityMatrix);
}
}
};
Painter.prototype.drawTile = function(tile, layers) {
this.setExtent(tile.tileExtent);
this.drawClippingMask(tile);
this.drawLayers(layers, tile.posMatrix, tile);
if (this.options.debug) {
draw.debug(this, tile);
}
};
Painter.prototype.drawLayers = function(layers, matrix, tile) {
for (var i = layers.length - 1; i >= 0; i--) {
var layer = layers[i];
if (layer.hidden)
continue;
draw[layer.type](this, layer, matrix, tile);
if (this.options.vertices) {
draw.vertices(this, layer, matrix, tile);
}
}
};
// Draws non-opaque areas. This is for debugging purposes.
Painter.prototype.drawStencilBuffer = function() {
var gl = this.gl;
gl.switchShader(this.fillShader, this.identityMatrix);
// Blend to the front, not the back.
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.stencilMask(0x00);
gl.stencilFunc(gl.EQUAL, 0x80, 0x80);
// Drw the filling quad where the stencil buffer isn't set.
gl.bindBuffer(gl.ARRAY_BUFFER, this.backgroundBuffer);
gl.vertexAttribPointer(this.fillShader.a_pos, this.backgroundBuffer.itemSize, gl.SHORT, false, 0, 0);
gl.uniform4fv(this.fillShader.u_color, [0, 0, 0, 0.5]);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.backgroundBuffer.itemCount);
// Revert blending mode to blend to the back.
gl.blendFunc(gl.ONE_MINUS_DST_ALPHA, gl.ONE);
};
Painter.prototype.translateMatrix = function(matrix, tile, translate, anchor) {
if (!translate[0] && !translate[1]) return matrix;
if (anchor === 'viewport') {
var sinA = Math.sin(-this.transform.angle);
var cosA = Math.cos(-this.transform.angle);
translate = [
translate[0] * cosA - translate[1] * sinA,
translate[0] * sinA + translate[1] * cosA
];
}
var tilePixelRatio = this.transform.scale / (1 << tile.coord.z) / (tile.tileExtent / tile.tileSize);
var translation = [
translate[0] / tilePixelRatio,
translate[1] / tilePixelRatio,
0
];
var translatedMatrix = new Float32Array(16);
mat4.translate(translatedMatrix, matrix, translation);
return translatedMatrix;
};
Painter.prototype.saveTexture = function(texture) {
var textures = this.reusableTextures[texture.size];
if (!textures) {
this.reusableTextures[texture.size] = [texture];
} else {
textures.push(texture);
}
};
Painter.prototype.getTexture = function(size) {
var textures = this.reusableTextures[size];
return textures && textures.length > 0 ? textures.pop() : null;
};
},{"../util/browser":85,"./draw_background":23,"./draw_debug":25,"./draw_fill":26,"./draw_line":27,"./draw_raster":28,"./draw_symbol":29,"./draw_vertices":30,"./frame_history":31,"./gl_util":32,"gl-matrix":104}],35:[function(require,module,exports){
'use strict';
var glify = undefined;
module.exports = {
"debug": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform float u_pointsize;uniform mat4 u_matrix;void main(){gl_Position=u_matrix*vec4(a_pos,step(32767.,a_pos.x),1);gl_PointSize=u_pointsize;}","fragment":"precision mediump float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"},
"dot": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform float u_size;attribute vec2 a_pos;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);gl_PointSize=u_size;}","fragment":"precision mediump float;uniform vec4 u_color;uniform float u_blur;void main(){float a,b;a=length(gl_PointCoord-.5);b=smoothstep(.5,.5-u_blur,a);gl_FragColor=u_color*b;}"},
"fill": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);gl_PointSize=2.;}","fragment":"precision mediump float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"},
"gaussian": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_offset;varying vec2 a[3];void main(){gl_Position=u_matrix*vec4(a_pos,0,1);vec2 b=gl_Position.xy/2.+.5;a[0]=b;a[1]=b+u_offset*1.1824255238063563;a[2]=b-u_offset*1.1824255238063563;}","fragment":"precision mediump float;uniform sampler2D u_image;varying vec2 a[3];void main(){vec4 b=vec4(0);b+=texture2D(u_image,a[0])*.40261994689424746;b+=texture2D(u_image,a[1])*.2986900265528763;b+=texture2D(u_image,a[2])*.2986900265528763;gl_FragColor=b;}"},
"line": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix;uniform float u_ratio,u_extra;uniform vec2 u_linewidth;uniform vec4 u_color;uniform mat2 u_antialiasingmatrix;varying vec2 a;varying float b,c;void main(){vec2 d,e;d=a_data.xy;e=mod(a_pos,2.);e.y=sign(e.y-.5);a=e;vec4 f=vec4(u_linewidth.s*d*.015873016,0,0);gl_Position=u_matrix*vec4(floor(a_pos*.5)+f.xy/u_ratio,0,1);float g,h,i;g=gl_Position.y/gl_Position.w;h=length(d)/length(u_antialiasingmatrix*d);i=1./(1.-g*u_extra);c=i*h;}","fragment":"precision mediump float;uniform vec2 u_linewidth,u_dasharray;uniform vec4 u_color;uniform float u_blur;varying vec2 a;varying float b,c;void main(){float d,e,f;d=length(a)*u_linewidth.s;e=u_blur*c;f=clamp(min(d-(u_linewidth.t-e),u_linewidth.s-d)/e,0.,1.);gl_FragColor=u_color*f;}"},
"linepattern": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix,u_exmatrix;uniform float u_ratio;uniform vec2 u_linewidth;uniform vec4 u_color;varying vec2 a;varying float b;void main(){vec2 c,e,f,g;c=a_data.xy;float d=a_data.z*128.+a_data.w;e=mod(a_pos,2.);e.y=sign(e.y-.5);a=e;f=c*.015873016;g=u_linewidth.s*f;gl_Position=u_matrix*vec4(floor(a_pos*.5)+g.xy/u_ratio,0,1);b=d;}","fragment":"precision mediump float;uniform vec2 u_linewidth,u_pattern_size_a,u_pattern_size_b,u_pattern_tl_a,u_pattern_br_a,u_pattern_tl_b,u_pattern_br_b;uniform float u_point,u_blur,u_fade,u_opacity;uniform sampler2D u_image;varying vec2 a;varying float b;void main(){float c,d,e,f,g,h;c=length(a)*u_linewidth.s;d=clamp(min(c-(u_linewidth.t-u_blur),u_linewidth.s-c)/u_blur,0.,1.);e=mod(b/u_pattern_size_a.x,1.);f=mod(b/u_pattern_size_b.x,1.);g=.5+a.y*u_linewidth.s/u_pattern_size_a.y;h=.5+a.y*u_linewidth.s/u_pattern_size_b.y;vec2 i,j;i=mix(u_pattern_tl_a,u_pattern_br_a,vec2(e,g));j=mix(u_pattern_tl_b,u_pattern_br_b,vec2(f,h));vec4 k=mix(texture2D(u_image,i),texture2D(u_image,j),u_fade);d*=u_opacity;gl_FragColor=k*d;}"},
"linesdfpattern": {"vertex":"precision mediump float;attribute vec2 a_pos;attribute vec4 a_data;uniform mat4 u_matrix,u_exmatrix;uniform vec2 u_linewidth,u_patternscale_a,u_patternscale_b;uniform float u_ratio,u_tex_y_a,u_tex_y_b;varying vec2 a,b,c;void main(){vec2 d,f;d=a_data.xy;float e=a_data.z*128.+a_data.w;f=mod(a_pos,2.);f.y=sign(f.y-.5);a=f;vec4 g=vec4(u_linewidth.s*d*.015873016,0,0);gl_Position=u_matrix*vec4(floor(a_pos*.5)+g.xy/u_ratio,0,1);b=vec2(e*u_patternscale_a.x,f.y*u_patternscale_a.y+u_tex_y_a);c=vec2(e*u_patternscale_b.x,f.y*u_patternscale_b.y+u_tex_y_b);}","fragment":"precision mediump float;uniform vec2 u_linewidth;uniform vec4 u_color;uniform float u_blur,u_sdfgamma,u_mix;uniform sampler2D u_image;varying vec2 a,b,c;void main(){float d,e,f,g,h;d=length(a)*u_linewidth.s;e=clamp(min(d-(u_linewidth.t-u_blur),u_linewidth.s-d)/u_blur,0.,1.);f=texture2D(u_image,b).a;g=texture2D(u_image,c).a;h=mix(f,g,u_mix);e*=smoothstep(.5-u_sdfgamma,.5+u_sdfgamma,h);gl_FragColor=u_color*e;}"},
"outline": {"vertex":"precision mediump float;attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_world;varying vec2 a;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(gl_Position.xy/gl_Position.w+1.)/2.*u_world;}","fragment":"precision mediump float;uniform vec4 u_color;varying vec2 a;void main(){float b,c;b=length(a-gl_FragCoord.xy);c=smoothstep(1.,0.,b);gl_FragColor=u_color*c;}"},
"pattern": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform mat3 u_patternmatrix_a,u_patternmatrix_b;attribute vec2 a_pos;varying vec2 a,b;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(u_patternmatrix_a*vec3(a_pos,1)).xy;b=(u_patternmatrix_b*vec3(a_pos,1)).xy;}","fragment":"precision mediump float;uniform float u_opacity,u_mix;uniform vec2 u_pattern_tl_a,u_pattern_br_a,u_pattern_tl_b,u_pattern_br_b;uniform sampler2D u_image;varying vec2 a,b;void main(){vec2 c,d,f,g;c=mod(a,1.);d=mix(u_pattern_tl_a,u_pattern_br_a,c);vec4 e,h;e=texture2D(u_image,d);f=mod(b,1.);g=mix(u_pattern_tl_b,u_pattern_br_b,f);h=texture2D(u_image,g);gl_FragColor=mix(e,h,u_mix)*u_opacity;}"},
"raster": {"vertex":"precision mediump float;uniform mat4 u_matrix;uniform vec2 u_tl_parent;uniform float u_scale_parent,u_buffer_scale;attribute vec2 a_pos,a_texture_pos;varying vec2 a,b;void main(){gl_Position=u_matrix*vec4(a_pos,0,1);a=(a_texture_pos/32767.-.5)/u_buffer_scale+.5;b=a*u_scale_parent+u_tl_parent;}","fragment":"precision mediump float;uniform float u_opacity0,u_opacity1,u_brightness_low,u_brightness_high,u_saturation_factor,u_contrast_factor;uniform sampler2D u_image0,u_image1;varying vec2 a,b;uniform vec3 u_spin_weights;void main(){vec4 c,d,e;c=texture2D(u_image0,a);d=texture2D(u_image1,b);e=c*u_opacity0+d*u_opacity1;vec3 f,h,i;f=e.rgb;f=vec3(dot(f,u_spin_weights.xyz),dot(f,u_spin_weights.zxy),dot(f,u_spin_weights.yzx));float g=(e.r+e.g+e.b)/3.;f+=(g-f)*u_saturation_factor;f=(f-.5)*u_contrast_factor+.5;h=vec3(u_brightness_low);i=vec3(u_brightness_high);gl_FragColor=vec4(mix(h,i,f),e.a);}"},
"icon": {"vertex":"precision mediump float;attribute vec2 a_pos,a_offset;attribute vec4 a_data1,a_data2;uniform mat4 u_matrix,u_exmatrix;uniform float u_zoom,u_fadedist,u_minfadezoom,u_maxfadezoom,u_fadezoom,u_opacity,u_extra;uniform bool u_skewed;uniform vec2 u_texsize;varying vec2 a;varying float b;void main(){vec2 c,e;c=a_data1.xy;float d,f,g,h,i,j;d=a_data1[2];e=a_data2.st;f=e[0];g=e[1];h=10.;i=2.-step(f,u_zoom)-(1.-step(g,u_zoom));j=clamp((u_fadezoom-d)/u_fadedist,0.,1.);if(u_fadedist>=0.)b=j;else b=1.-j;if(u_maxfadezoom<d)b=0.;if(u_minfadezoom>=d)b=1.;i+=step(b,0.);if(u_skewed){vec4 k=u_exmatrix*vec4(a_offset/64.,0,0);gl_Position=u_matrix*vec4(a_pos+k.xy,0,1);gl_Position.z+=i*gl_Position.w;}else{vec4 k=u_exmatrix*vec4(a_offset/64.,i,0);gl_Position=u_matrix*vec4(a_pos,0,1)+k;}a=c/u_texsize;b*=u_opacity;}","fragment":"precision mediump float;uniform sampler2D u_texture;varying vec2 a;varying float b;void main(){gl_FragColor=texture2D(u_texture,a)*b;}"},
"sdf": {"vertex":"precision mediump float;attribute vec2 a_pos,a_offset;attribute vec4 a_data1,a_data2;uniform mat4 u_matrix,u_exmatrix;uniform float u_zoom,u_fadedist,u_minfadezoom,u_maxfadezoom,u_fadezoom,u_extra;uniform bool u_skewed;uniform vec2 u_texsize;varying vec2 a;varying float b,c;void main(){vec2 d,f;d=a_data1.xy;float e,g,h,i,j,k,l;e=a_data1[2];f=a_data2.st;g=f[0];h=f[1];i=2.-step(g,u_zoom)-(1.-step(h,u_zoom));j=clamp((u_fadezoom-e)/u_fadedist,0.,1.);if(u_fadedist>=0.)b=j;else b=1.-j;if(u_maxfadezoom<e)b=0.;if(u_minfadezoom>=e)b=1.;i+=step(b,0.);if(u_skewed){vec4 k=u_exmatrix*vec4(a_offset/64.,0,0);gl_Position=u_matrix*vec4(a_pos+k.xy,0,1);gl_Position.z+=i*gl_Position.w;}else{vec4 k=u_exmatrix*vec4(a_offset/64.,i,0);gl_Position=u_matrix*vec4(a_pos,0,1)+k;}k=gl_Position.y/gl_Position.w;l=1./(1.-k*u_extra);c=l;a=d/u_texsize;}","fragment":"precision mediump float;uniform sampler2D u_texture;uniform vec4 u_color;uniform float u_buffer,u_gamma;varying vec2 a;varying float b,c;void main(){float d,e,f;d=u_gamma*c;e=texture2D(u_texture,a).a;f=smoothstep(u_buffer-d,u_buffer+d,e)*b;gl_FragColor=u_color*f;}"},
"collisionbox": {"vertex":"precision mediump float;attribute vec2 a_pos,a_extrude,a_data;uniform mat4 u_matrix;uniform float u_scale;varying float a,b;void main(){gl_Position=u_matrix*vec4(a_pos+a_extrude/u_scale,0,1);a=a_data.x;b=a_data.y;}","fragment":"precision mediump float;uniform float u_zoom,u_maxzoom;varying float a,b;void main(){float c=.5;gl_FragColor=vec4(0,1,0,1)*c;if(b>u_zoom)gl_FragColor=vec4(1,0,0,1)*c;if(u_zoom>=a)gl_FragColor=vec4(0,0,0,1)*c*.25;if(b>=u_maxzoom)gl_FragColor=vec4(0,0,1,1)*c*.2;}"}
};
},{}],36:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var Evented = require('../util/evented');
var TilePyramid = require('./tile_pyramid');
var Source = require('./source');
var urlResolve = require('resolve-url');
module.exports = GeoJSONSource;
/**
* Create a GeoJSON data source instance given an options object
* @class GeoJSONSource
* @param {Object} [options]
* @param {Object|String} options.data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.
* @param {Number} [options.maxzoom=14] Maximum zoom to preserve detail at.
* @example
* var sourceObj = new mapboxgl.GeoJSONSource({
* data: {
* "type": "FeatureCollection",
* "features": [{
* "type": "Feature",
* "geometry": {
* "type": "Point",
* "coordinates": [
* -76.53063297271729,
* 39.18174077994108
* ]
* }
* }]
* }
* });
* map.addSource('some id', sourceObj); // add
* map.removeSource('some id'); // remove
*/
function GeoJSONSource(options) {
options = options || {};
this._data = options.data;
if (options.maxzoom !== undefined) this.maxzoom = options.maxzoom;
this._pyramid = new TilePyramid({
tileSize: 512,
minzoom: this.minzoom,
maxzoom: this.maxzoom,
cacheSize: 20,
load: this._loadTile.bind(this),
abort: this._abortTile.bind(this),
unload: this._unloadTile.bind(this),
add: this._addTile.bind(this),
remove: this._removeTile.bind(this)
});
}
GeoJSONSource.prototype = util.inherit(Evented, /** @lends GeoJSONSource.prototype */{
minzoom: 0,
maxzoom: 14,
_dirty: true,
/**
* Update source geojson data and rerender map
*
* @param {Object|String} data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.
* @returns {GeoJSONSource} this
*/
setData: function(data) {
this._data = data;
this._dirty = true;
this.fire('change');
if (this.map)
this.update(this.map.transform);
return this;
},
onAdd: function(map) {
this.map = map;
},
loaded: function() {
return this._loaded && this._pyramid.loaded();
},
update: function(transform) {
if (this._dirty) {
this._updateData();
}
if (this._loaded) {
this._pyramid.update(this.used, transform);
}
},
reload: function() {
this._pyramid.reload();
},
render: Source._renderTiles,
featuresAt: Source._vectorFeaturesAt,
_updateData: function() {
this._dirty = false;
var data = this._data;
if (typeof data === 'string') {
data = urlResolve(window.location.href, data);
}
this.workerID = this.dispatcher.send('parse geojson', {
data: data,
tileSize: 512,
source: this.id,
maxZoom: this.maxzoom
}, function(err) {
if (err) {
this.fire('error', {error: err});
return;
}
this._loaded = true;
this._pyramid.reload();
this.fire('change');
}.bind(this));
},
_loadTile: function(tile) {
var overscaling = tile.coord.z > this.maxzoom ? Math.pow(2, tile.coord.z - this.maxzoom) : 1;
var params = {
uid: tile.uid,
coord: tile.coord,
zoom: tile.coord.z,
maxZoom: this.maxzoom,
tileSize: 512,
source: this.id,
overscaling: overscaling,
angle: this.map.transform.angle,
pitch: this.map.transform.pitch,
collisionDebug: this.map.collisionDebug
};
tile.workerID = this.dispatcher.send('load geojson tile', params, function(err, data) {
tile.unloadVectorData(this.map.painter);
if (tile.aborted)
return;
if (err) {
this.fire('tile.error', {tile: tile});
return;
}
tile.loadVectorData(data);
this.fire('tile.load', {tile: tile});
}.bind(this), this.workerID);
},
_abortTile: function(tile) {
tile.aborted = true;
},
_addTile: function(tile) {
this.fire('tile.add', {tile: tile});
},
_removeTile: function(tile) {
this.fire('tile.remove', {tile: tile});
},
_unloadTile: function(tile) {
tile.unloadVectorData(this.map.painter);
this.glyphAtlas.removeGlyphs(tile.uid);
this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID);
}
});
},{"../util/evented":90,"../util/util":96,"./source":39,"./tile_pyramid":42,"resolve-url":115}],37:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
var VectorTileFeature = require('vector-tile').VectorTileFeature;
module.exports = GeoJSONWrapper;
// conform to vectortile api
function GeoJSONWrapper(features) {
this.features = features;
this.length = features.length;
}
GeoJSONWrapper.prototype.feature = function(i) {
return new FeatureWrapper(this.features[i]);
};
function FeatureWrapper(feature) {
this.type = feature.type;
this.rawGeometry = feature.type === 1 ? [feature.geometry] : feature.geometry;
this.properties = feature.tags;
this.extent = 4096;
}
FeatureWrapper.prototype.loadGeometry = function() {
var rings = this.rawGeometry;
this.geometry = [];
for (var i = 0; i < rings.length; i++) {
var ring = rings[i],
newRing = [];
for (var j = 0; j < ring.length; j++) {
newRing.push(new Point(ring[j][0], ring[j][1]));
}
this.geometry.push(newRing);
}
return this.geometry;
};
FeatureWrapper.prototype.bbox = function() {
if (!this.geometry) this.loadGeometry();
var rings = this.geometry,
x1 = Infinity,
x2 = -Infinity,
y1 = Infinity,
y2 = -Infinity;
for (var i = 0; i < rings.length; i++) {
var ring = rings[i];
for (var j = 0; j < ring.length; j++) {
var coord = ring[j];
x1 = Math.min(x1, coord.x);
x2 = Math.max(x2, coord.x);
y1 = Math.min(y1, coord.y);
y2 = Math.max(y2, coord.y);
}
}
return [x1, y1, x2, y2];
};
FeatureWrapper.prototype.toGeoJSON = VectorTileFeature.prototype.toGeoJSON;
},{"point-geometry":113,"vector-tile":117}],38:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var ajax = require('../util/ajax');
var Evented = require('../util/evented');
var Source = require('./source');
var normalizeURL = require('../util/mapbox').normalizeTileURL;
module.exports = RasterTileSource;
function RasterTileSource(options) {
util.extend(this, util.pick(options, ['url', 'tileSize']));
Source._loadTileJSON.call(this, options);
}
RasterTileSource.prototype = util.inherit(Evented, {
minzoom: 0,
maxzoom: 22,
tileSize: 512,
_loaded: false,
onAdd: function(map) {
this.map = map;
},
loaded: function() {
return this._pyramid && this._pyramid.loaded();
},
update: function(transform) {
if (this._pyramid) {
this._pyramid.update(this.used, transform, this.map.style.rasterFadeDuration);
}
},
render: Source._renderTiles,
_loadTile: function(tile) {
ajax.getImage(normalizeURL(tile.coord.url(this.tiles), this.url), function(err, img) {
if (tile.aborted)
return;
if (err) {
this.fire('tile.error', {tile: tile});
return;
}
var gl = this.map.painter.gl;
tile.texture = this.map.painter.getTexture(img.width);
if (tile.texture) {
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, img);
} else {
tile.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
tile.texture.size = img.width;
}
gl.generateMipmap(gl.TEXTURE_2D);
tile.timeAdded = new Date().getTime();
this.map.animationLoop.set(this.style.rasterFadeDuration);
tile.source = this;
tile.loaded = true;
this.fire('tile.load', {tile: tile});
}.bind(this));
},
_abortTile: function(tile) {
tile.aborted = true;
},
_addTile: function(tile) {
this.fire('tile.add', {tile: tile});
},
_removeTile: function(tile) {
this.fire('tile.remove', {tile: tile});
},
_unloadTile: function(tile) {
if (tile.texture) this.map.painter.saveTexture(tile.texture);
},
featuresAt: function(point, params, callback) {
callback(null, []);
}
});
},{"../util/ajax":84,"../util/evented":90,"../util/mapbox":93,"../util/util":96,"./source":39}],39:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var ajax = require('../util/ajax');
var browser = require('../util/browser');
var TilePyramid = require('./tile_pyramid');
var TileCoord = require('./tile_coord');
var normalizeURL = require('../util/mapbox').normalizeSourceURL;
exports._loadTileJSON = function(options) {
var loaded = function(err, tileJSON) {
if (err) {
this.fire('error', {error: err});
return;
}
util.extend(this, util.pick(tileJSON,
['tiles', 'minzoom', 'maxzoom', 'attribution']));
this._pyramid = new TilePyramid({
tileSize: this.tileSize,
cacheSize: 20,
minzoom: this.minzoom,
maxzoom: this.maxzoom,
reparseOverscaled: this.reparseOverscaled,
load: this._loadTile.bind(this),
abort: this._abortTile.bind(this),
unload: this._unloadTile.bind(this),
add: this._addTile.bind(this),
remove: this._removeTile.bind(this),
redoPlacement: this._redoTilePlacement ? this._redoTilePlacement.bind(this) : undefined
});
this.fire('load');
}.bind(this);
if (options.url) {
ajax.getJSON(normalizeURL(options.url), loaded);
} else {
browser.frame(loaded.bind(this, null, options));
}
};
exports._renderTiles = function(layers, painter) {
if (!this._pyramid)
return;
var ids = this._pyramid.renderedIDs();
for (var i = 0; i < ids.length; i++) {
var tile = this._pyramid.getTile(ids[i]),
// coord is different than tile.coord for wrapped tiles since the actual
// tile object is shared between all the visible copies of that tile.
coord = TileCoord.fromID(ids[i]),
z = coord.z,
x = coord.x,
y = coord.y,
w = coord.w;
// if z > maxzoom then the tile is actually a overscaled maxzoom tile,
// so calculate the matrix the maxzoom tile would use.
z = Math.min(z, this.maxzoom);
x += w * (1 << z);
tile.calculateMatrices(z, x, y, painter.transform, painter);
painter.drawTile(tile, layers);
}
};
exports._vectorFeaturesAt = function(coord, params, callback) {
if (!this._pyramid)
return callback(null, []);
var result = this._pyramid.tileAt(coord);
if (!result)
return callback(null, []);
this.dispatcher.send('query features', {
uid: result.tile.uid,
x: result.x,
y: result.y,
scale: result.scale,
source: this.id,
params: params
}, callback, result.tile.workerID);
};
/*
* Create a tiled data source instance given an options object
*
* @param {Object} options
* @param {String} options.type Either `raster` or `vector`.
* @param {String} options.url A tile source URL. This should either be `mapbox://{mapid}` or a full `http[s]` url that points to a TileJSON endpoint.
* @param {Array} options.tiles An array of tile sources. If `url` is not specified, `tiles` can be used instead to specify tile sources, as in the TileJSON spec. Other TileJSON keys such as `minzoom` and `maxzoom` can be specified in a source object if `tiles` is used.
* @param {String} options.id An optional `id` to assign to the source
* @param {Number} [options.tileSize=512] Optional tile size (width and height in pixels, assuming tiles are square). This option is only configurable for raster sources
* @param {Number} options.cacheSize Optional max number of tiles to cache at any given time
* @example
* var sourceObj = new mapboxgl.Source.create({
* type: 'vector',
* url: 'mapbox://mapbox.mapbox-streets-v5'
* });
* map.addSource('some id', sourceObj); // add
* map.removeSource('some id'); // remove
*/
exports.create = function(source) {
// This is not at file scope in order to avoid a circular require.
var sources = {
vector: require('./vector_tile_source'),
raster: require('./raster_tile_source'),
geojson: require('./geojson_source'),
video: require('./video_source')
};
for (var type in sources) {
if (source instanceof sources[type]) {
return source;
}
}
return new sources[source.type](source);
};
},{"../util/ajax":84,"../util/browser":85,"../util/mapbox":93,"../util/util":96,"./geojson_source":36,"./raster_tile_source":38,"./tile_coord":41,"./tile_pyramid":42,"./vector_tile_source":43,"./video_source":44}],40:[function(require,module,exports){
'use strict';
var glmatrix = require('gl-matrix');
var mat2 = glmatrix.mat2;
var mat4 = glmatrix.mat4;
var util = require('../util/util');
var BufferSet = require('../data/buffer/buffer_set');
module.exports = Tile;
/**
* A tile object is the combination of a Coordinate, which defines
* its place, as well as a unique ID and data tracking for its content
*
* @param {Coordinate} coord
* @param {number} size
*/
function Tile(coord, size) {
this.coord = coord;
this.uid = util.uniqueId();
this.loaded = false;
this.uses = 0;
this.tileSize = size;
}
Tile.prototype = {
// todo unhardcode
tileExtent: 4096,
/**
* Calculate the internal posMatrix that this tile uses to display
* itself in a map, given a coordinate as (z, x, y) and a transform
* @param {number} z
* @param {number} x
* @param {number} y
* @param {Object} transform
*/
calculateMatrices: function(z, x, y, transform) {
// Initialize model-view matrix that converts from the tile coordinates
// to screen coordinates.
var tileScale = Math.pow(2, z);
var scale = transform.worldSize / tileScale;
// TODO: remove
this.scale = scale;
// The position matrix
this.posMatrix = new Float64Array(16);
mat4.identity(this.posMatrix);
mat4.translate(this.posMatrix, this.posMatrix, [x * scale, y * scale, 0]);
mat4.scale(this.posMatrix, this.posMatrix, [ scale / this.tileExtent, scale / this.tileExtent, 1 ]);
mat4.multiply(this.posMatrix, transform.getProjMatrix(), this.posMatrix);
// The extrusion matrix.
this.exMatrix = mat4.create();
mat4.ortho(this.exMatrix, 0, transform.width, transform.height, 0, 0, -1);
//mat4.rotateZ(this.exMatrix, this.exMatrix, -transform.angle);
// 2x2 matrix for rotating points
this.rotationMatrix = mat2.create();
mat2.rotate(this.rotationMatrix, this.rotationMatrix, transform.angle);
this.posMatrix = new Float32Array(this.posMatrix);
},
/**
* Given a coordinate position, zoom that coordinate to my zoom and
* scale and return a position in x, y, scale
* @param {Coordinate} coord
* @returns {Object} position
*/
positionAt: function(coord, sourceMaxZoom) {
coord = coord.zoomTo(Math.min(this.coord.z, sourceMaxZoom));
return {
x: (coord.column - this.coord.x) * 4096,
y: (coord.row - this.coord.y) * 4096,
scale: this.scale
};
},
/**
* Given a data object with a 'buffers' property, load it into
* this tile's elementGroups and buffers properties and set loaded
* to true. If the data is null, like in the case of an empty
* GeoJSON tile, no-op but still set loaded to true.
* @param {Object} data
* @returns {undefined}
*/
loadVectorData: function(data) {
this.loaded = true;
// empty GeoJSON tile
if (!data) return;
this.buffers = new BufferSet(data.buffers);
this.elementGroups = data.elementGroups;
this.tileExtent = data.extent;
},
/**
* given a data object and a GL painter, destroy and re-create
* all of its buffers.
* @param {Object} data
* @param {Object} painter
* @returns {undefined}
*/
reloadSymbolData: function(data, painter) {
if (!this.buffers) {
// the tile has been destroyed
return;
}
this.buffers.glyphVertex.destroy(painter.gl);
this.buffers.glyphElement.destroy(painter.gl);
this.buffers.iconVertex.destroy(painter.gl);
this.buffers.iconElement.destroy(painter.gl);
this.buffers.collisionBoxVertex.destroy(painter.gl);
var buffers = new BufferSet(data.buffers);
this.buffers.glyphVertex = buffers.glyphVertex;
this.buffers.glyphElement = buffers.glyphElement;
this.buffers.iconVertex = buffers.iconVertex;
this.buffers.iconElement = buffers.iconElement;
this.buffers.collisionBoxVertex = buffers.collisionBoxVertex;
for (var id in data.elementGroups) {
this.elementGroups[id] = data.elementGroups[id];
}
},
/**
* Make sure that this tile doesn't own any data within a given
* painter, so that it doesn't consume any memory or maintain
* any references to the painter.
* @param {Object} painter gl painter object
* @returns {undefined}
*/
unloadVectorData: function(painter) {
for (var b in this.buffers) {
this.buffers[b].destroy(painter.gl);
}
this.buffers = null;
}
};
},{"../data/buffer/buffer_set":2,"../util/util":96,"gl-matrix":104}],41:[function(require,module,exports){
'use strict';
module.exports = TileCoord;
function TileCoord(z, x, y, w) {
if (w === undefined) w = 0;
this.z = z;
this.x = x;
this.y = y;
this.w = w;
// calculate id
w *= 2;
if (w < 0) w = w * -1 - 1;
var dim = 1 << this.z;
this.id = ((dim * dim * w + dim * this.y + this.x) * 32) + this.z;
}
TileCoord.prototype.toString = function() {
return this.z + "/" + this.x + "/" + this.y;
};
// Parse a packed integer id into a TileCoord object
TileCoord.fromID = function(id) {
var z = id % 32, dim = 1 << z;
var xy = ((id - z) / 32);
var x = xy % dim, y = ((xy - x) / dim) % dim;
var w = Math.floor(xy / (dim * dim));
if (w % 2 !== 0) w = w * -1 - 1;
w /= 2;
return new TileCoord(z, x, y, w);
};
// given a list of urls, choose a url template and return a tile URL
TileCoord.prototype.url = function(urls, sourceMaxZoom) {
return urls[(this.x + this.y) % urls.length]
.replace('{prefix}', (this.x % 16).toString(16) + (this.y % 16).toString(16))
.replace('{z}', Math.min(this.z, sourceMaxZoom || this.z))
.replace('{x}', this.x)
.replace('{y}', this.y);
};
// Return the coordinate of the parent tile
TileCoord.prototype.parent = function(sourceMaxZoom) {
if (this.z === 0) return null;
// the id represents an overscaled tile, return the same coordinates with a lower z
if (this.z > sourceMaxZoom) {
return new TileCoord(this.z - 1, this.x, this.y, this.w);
}
return new TileCoord(this.z - 1, Math.floor(this.x / 2), Math.floor(this.y / 2), this.w);
};
TileCoord.prototype.wrapped = function() {
return new TileCoord(this.z, this.x, this.y, 0);
};
// Return the coordinates of the tile's children
TileCoord.prototype.children = function(sourceMaxZoom) {
if (this.z >= sourceMaxZoom) {
// return a single tile coord representing a an overscaled tile
return [new TileCoord(this.z + 1, this.x, this.y, this.w)];
}
var z = this.z + 1;
var x = this.x * 2;
var y = this.y * 2;
return [
new TileCoord(z, x, y, this.w),
new TileCoord(z, x + 1, y, this.w),
new TileCoord(z, x, y + 1, this.w),
new TileCoord(z, x + 1, y + 1, this.w)
];
};
// Taken from polymaps src/Layer.js
// https://github.com/simplegeo/polymaps/blob/master/src/Layer.js#L333-L383
function edge(a, b) {
if (a.row > b.row) { var t = a; a = b; b = t; }
return {
x0: a.column,
y0: a.row,
x1: b.column,
y1: b.row,
dx: b.column - a.column,
dy: b.row - a.row
};
}
function scanSpans(e0, e1, ymin, ymax, scanLine) {
var y0 = Math.max(ymin, Math.floor(e1.y0));
var y1 = Math.min(ymax, Math.ceil(e1.y1));
// sort edges by x-coordinate
if ((e0.x0 === e1.x0 && e0.y0 === e1.y0) ?
(e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) :
(e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) {
var t = e0; e0 = e1; e1 = t;
}
// scan lines!
var m0 = e0.dx / e0.dy;
var m1 = e1.dx / e1.dy;
var d0 = e0.dx > 0; // use y + 1 to compute x0
var d1 = e1.dx < 0; // use y + 1 to compute x1
for (var y = y0; y < y1; y++) {
var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0;
var x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0;
scanLine(Math.floor(x1), Math.ceil(x0), y);
}
}
function scanTriangle(a, b, c, ymin, ymax, scanLine) {
var ab = edge(a, b),
bc = edge(b, c),
ca = edge(c, a);
var t;
// sort edges by y-length
if (ab.dy > bc.dy) { t = ab; ab = bc; bc = t; }
if (ab.dy > ca.dy) { t = ab; ab = ca; ca = t; }
if (bc.dy > ca.dy) { t = bc; bc = ca; ca = t; }
// scan span! scan span!
if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine);
if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine);
}
TileCoord.cover = function(z, bounds, actualZ) {
var tiles = 1 << z;
var t = {};
function scanLine(x0, x1, y) {
var x, wx;
if (y >= 0 && y <= tiles) {
for (x = x0; x < x1; x++) {
wx = (x + tiles) % tiles;
var coord = new TileCoord(actualZ, wx, y, Math.floor(x / tiles));
t[coord.id] = coord;
}
}
}
// Divide the screen up in two triangles and scan each of them:
// +---/
// | / |
// /---+
scanTriangle(bounds[0], bounds[1], bounds[2], 0, tiles, scanLine);
scanTriangle(bounds[2], bounds[3], bounds[0], 0, tiles, scanLine);
return Object.keys(t).map(function(id) {
return t[id];
});
};
},{}],42:[function(require,module,exports){
'use strict';
var Tile = require('./tile');
var TileCoord = require('./tile_coord');
var Point = require('point-geometry');
var Cache = require('../util/mru_cache');
var util = require('../util/util');
module.exports = TilePyramid;
/**
* A tile pyramid is a specialized cache and datastructure
* that contains tiles. It's used by sources to manage their
* data.
*
* @param {Object} options
* @param {number} options.tileSize
* @param {number} options.minzoom
* @param {number} options.maxzoom
*/
function TilePyramid(options) {
this.tileSize = options.tileSize;
this.minzoom = options.minzoom;
this.maxzoom = options.maxzoom;
this.reparseOverscaled = options.reparseOverscaled;
this._load = options.load;
this._abort = options.abort;
this._unload = options.unload;
this._add = options.add;
this._remove = options.remove;
this._redoPlacement = options.redoPlacement;
this._tiles = {};
this._cache = new Cache(options.cacheSize, function(tile) { return this._unload(tile); }.bind(this));
}
TilePyramid.prototype = {
/**
* Confirm that every tracked tile is loaded.
* @returns {boolean} whether all tiles are loaded.
* @private
*/
loaded: function() {
for (var t in this._tiles) {
if (!this._tiles[t].loaded)
return false;
}
return true;
},
/**
* Return all tile ids ordered with z-order, and cast to numbers
* @returns {Array<number>} ids
* @private
*/
orderedIDs: function() {
return Object.keys(this._tiles)
.sort(function(a, b) { return (b % 32) - (a % 32); })
.map(function(id) { return +id; });
},
renderedIDs: function() {
return this.orderedIDs().filter(function(id) {
return this._tiles[id].loaded && !this._coveredTiles[id];
}.bind(this));
},
reload: function() {
this._cache.reset();
for (var i in this._tiles) {
this._load(this._tiles[i]);
}
},
/**
* Get a specific tile by id
* @param {string|number} id tile id
* @returns {Object} tile
* @private
*/
getTile: function(id) {
return this._tiles[id];
},
/**
* get the zoom level adjusted for the difference in map and source tilesizes
* @param {Object} transform
* @returns {number} zoom level
* @private
*/
getZoom: function(transform) {
return transform.zoom + Math.log(transform.tileSize / this.tileSize) / Math.LN2;
},
/**
* Return a zoom level that will cover all tiles in a given transform
* @param {Object} transform
* @returns {number} zoom level
*/
coveringZoomLevel: function(transform) {
return Math.floor(this.getZoom(transform));
},
/**
* Given a transform, return all coordinates that could cover that
* transform for a covering zoom level.
* @param {Object} transform
* @returns {Array<Tile>} tiles
*/
coveringTiles: function(transform) {
var z = this.coveringZoomLevel(transform);
var actualZ = z;
if (z < this.minzoom) return [];
if (z > this.maxzoom) z = this.maxzoom;
var tr = transform,
tileCenter = tr.locationCoordinate(tr.center)._zoomTo(z),
centerPoint = new Point(tileCenter.column - 0.5, tileCenter.row - 0.5);
return TileCoord.cover(z, [
tr.pointCoordinate(new Point(0, 0))._zoomTo(z),
tr.pointCoordinate(new Point(tr.width, 0))._zoomTo(z),
tr.pointCoordinate(new Point(tr.width, tr.height))._zoomTo(z),
tr.pointCoordinate(new Point(0, tr.height))._zoomTo(z)
], this.reparseOverscaled ? actualZ : z).sort(function(a, b) {
return centerPoint.dist(a) - centerPoint.dist(b);
});
},
/**
* Recursively find children of the given tile (up to maxCoveringZoom) that are already loaded;
* adds found tiles to retain object; returns true if children completely cover the tile
*
* @param {Coordinate} coord
* @param {number} maxCoveringZoom
* @param {boolean} retain
* @returns {boolean} whether the operation was complete
* @private
*/
findLoadedChildren: function(coord, maxCoveringZoom, retain) {
var complete = true;
var z = coord.z;
var coords = coord.children(this.maxzoom);
for (var i = 0; i < coords.length; i++) {
var id = coords[i].id;
if (this._tiles[id] && this._tiles[id].loaded) {
retain[id] = true;
} else {
complete = false;
if (z < maxCoveringZoom) {
// Go further down the hierarchy to find more unloaded children.
this.findLoadedChildren(coords[i], maxCoveringZoom, retain);
}
}
}
return complete;
},
/**
* Find a loaded parent of the given tile (up to minCoveringZoom);
* adds the found tile to retain object and returns the tile if found
*
* @param {Coordinate} coord
* @param {number} minCoveringZoom
* @param {boolean} retain
* @returns {Tile} tile object
*/
findLoadedParent: function(coord, minCoveringZoom, retain) {
for (var z = coord.z - 1; z >= minCoveringZoom; z--) {
coord = coord.parent(this.maxzoom);
var tile = this._tiles[coord.id];
if (tile && tile.loaded) {
retain[coord.id] = true;
return tile;
}
}
},
/**
* Removes tiles that are outside the viewport and adds new tiles that
* are inside the viewport.
*/
update: function(used, transform, fadeDuration) {
var i;
var coord;
var tile;
// Determine the overzooming/underzooming amounts.
var zoom = Math.floor(this.getZoom(transform));
var minCoveringZoom = util.clamp(zoom - 10, this.minzoom, this.maxzoom);
var maxCoveringZoom = util.clamp(zoom + 1, this.minzoom, this.maxzoom);
// Retain is a list of tiles that we shouldn't delete, even if they are not
// the most ideal tile for the current viewport. This may include tiles like
// parent or child tiles that are *already* loaded.
var retain = {};
var now = new Date().getTime();
// Covered is a list of retained tiles who's areas are full covered by other,
// better, retained tiles. They are not drawn separately.
this._coveredTiles = {};
var required = used ? this.coveringTiles(transform) : [];
for (i = 0; i < required.length; i++) {
coord = required[i];
tile = this.addTile(coord);
retain[coord.id] = true;
if (tile.loaded)
continue;
// The tile we require is not yet loaded.
// Retain child or parent tiles that cover the same area.
if (!this.findLoadedChildren(coord, maxCoveringZoom, retain)) {
this.findLoadedParent(coord, minCoveringZoom, retain);
}
}
for (var id in retain) {
coord = TileCoord.fromID(id);
tile = this._tiles[id];
if (tile && tile.timeAdded > now - (fadeDuration || 0)) {
// This tile is still fading in. Find tiles to cross-fade with it.
if (this.findLoadedChildren(coord, maxCoveringZoom, retain)) {
this._coveredTiles[id] = true;
retain[id] = true;
} else {
this.findLoadedParent(coord, minCoveringZoom, retain);
}
}
}
// Remove the tiles we don't need anymore.
var remove = util.keysDifference(this._tiles, retain);
for (i = 0; i < remove.length; i++) {
this.removeTile(+remove[i]);
}
},
/**
* Add a tile, given its coordinate, to the pyramid.
* @param {Coordinate} coord
* @returns {Coordinate} the coordinate.
*/
addTile: function(coord) {
var tile = this._tiles[coord.id];
if (tile)
return tile;
var wrapped = coord.wrapped();
tile = this._tiles[wrapped.id];
if (!tile) {
tile = this._cache.get(wrapped.id);
if (tile && this._redoPlacement) {
this._redoPlacement(tile);
}
}
if (!tile) {
var zoom = coord.z;
var overscaling = zoom > this.maxzoom ? Math.pow(2, zoom - this.maxzoom) : 1;
tile = new Tile(wrapped, this.tileSize * overscaling);
this._load(tile);
}
tile.uses++;
this._tiles[coord.id] = tile;
this._add(tile, coord);
return tile;
},
/**
* Remove a tile, given its id, from the pyramid
* @param {string|number} id tile id
* @returns {undefined} nothing
* @private
*/
removeTile: function(id) {
var tile = this._tiles[id];
if (!tile)
return;
tile.uses--;
delete this._tiles[id];
this._remove(tile);
if (tile.uses > 0)
return;
if (tile.loaded) {
this._cache.add(tile.coord.wrapped().id, tile);
} else {
this._abort(tile);
this._unload(tile);
}
},
/**
* Remove all tiles from this pyramid
*/
clearTiles: function() {
for (var id in this._tiles)
this.removeTile(id);
this._cache.reset();
},
/**
* For a given coordinate, search through our current tiles and attempt
* to find a tile at that point
* @param {Coordinate} coord
* @returns {Object} tile
* @private
*/
tileAt: function(coord) {
var ids = this.orderedIDs();
for (var i = 0; i < ids.length; i++) {
var tile = this._tiles[ids[i]];
var pos = tile.positionAt(coord, this.maxzoom);
if (pos && pos.x >= 0 && pos.x < 4096 && pos.y >= 0 && pos.y < 4096) {
// The click is within the viewport. There is only ever one tile in
// a layer that has this property.
return {
tile: tile,
x: pos.x,
y: pos.y,
scale: pos.scale
};
}
}
}
};
},{"../util/mru_cache":94,"../util/util":96,"./tile":40,"./tile_coord":41,"point-geometry":113}],43:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var Evented = require('../util/evented');
var Source = require('./source');
module.exports = VectorTileSource;
function VectorTileSource(options) {
util.extend(this, util.pick(options, ['url', 'tileSize']));
if (this.tileSize !== 512) {
throw new Error('vector tile sources must have a tileSize of 512');
}
Source._loadTileJSON.call(this, options);
}
VectorTileSource.prototype = util.inherit(Evented, {
minzoom: 0,
maxzoom: 22,
tileSize: 512,
reparseOverscaled: true,
_loaded: false,
onAdd: function(map) {
this.map = map;
},
loaded: function() {
return this._pyramid && this._pyramid.loaded();
},
update: function(transform) {
if (this._pyramid) {
this._pyramid.update(this.used, transform);
}
},
reload: function() {
this._pyramid.reload();
},
redoPlacement: function() {
if (!this._pyramid) {
return;
}
var ids = this._pyramid.orderedIDs();
for (var i = 0; i < ids.length; i++) {
var tile = this._pyramid.getTile(ids[i]);
this._redoTilePlacement(tile);
}
},
render: Source._renderTiles,
featuresAt: Source._vectorFeaturesAt,
_loadTile: function(tile) {
var overscaling = tile.coord.z > this.maxzoom ? Math.pow(2, tile.coord.z - this.maxzoom) : 1;
var params = {
url: tile.coord.url(this.tiles, this.maxzoom),
uid: tile.uid,
coord: tile.coord,
zoom: tile.coord.z,
maxZoom: this.maxzoom,
tileSize: this.tileSize * overscaling,
source: this.id,
overscaling: overscaling,
angle: this.map.transform.angle,
pitch: this.map.transform.pitch,
collisionDebug: this.map.collisionDebug
};
if (tile.workerID) {
this.dispatcher.send('reload tile', params, this._tileLoaded.bind(this, tile), tile.workerID);
} else {
tile.workerID = this.dispatcher.send('load tile', params, this._tileLoaded.bind(this, tile));
}
},
_tileLoaded: function(tile, err, data) {
if (tile.aborted)
return;
if (err) {
this.fire('tile.error', {tile: tile});
return;
}
tile.loadVectorData(data);
if (tile.redoWhenDone) {
tile.redoWhenDone = false;
this._redoTilePlacement(tile);
}
this.fire('tile.load', {tile: tile});
},
_abortTile: function(tile) {
tile.aborted = true;
this.dispatcher.send('abort tile', { uid: tile.uid, source: this.id }, null, tile.workerID);
},
_addTile: function(tile) {
this.fire('tile.add', {tile: tile});
},
_removeTile: function(tile) {
this.fire('tile.remove', {tile: tile});
},
_unloadTile: function(tile) {
tile.unloadVectorData(this.map.painter);
this.glyphAtlas.removeGlyphs(tile.uid);
this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID);
},
_redoTilePlacement: function(tile) {
if (!tile.loaded || tile.redoingPlacement) {
tile.redoWhenDone = true;
return;
}
tile.redoingPlacement = true;
this.dispatcher.send('redo placement', {
uid: tile.uid,
source: this.id,
angle: this.map.transform.angle,
pitch: this.map.transform.pitch,
collisionDebug: this.map.collisionDebug
}, done.bind(this), tile.workerID);
function done(_, data) {
tile.reloadSymbolData(data, this.map.painter);
this.fire('tile.load', {tile: tile});
tile.redoingPlacement = false;
if (tile.redoWhenDone) {
this._redoTilePlacement(tile);
tile.redoWhenDone = false;
}
}
}
});
},{"../util/evented":90,"../util/util":96,"./source":39}],44:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var Tile = require('./tile');
var LatLng = require('../geo/lat_lng');
var Point = require('point-geometry');
var Evented = require('../util/evented');
var Coordinate = require('../geo/coordinate');
var ajax = require('../util/ajax');
module.exports = VideoSource;
/**
* Create a Video data source instance given an options object
* @class VideoSource
* @param {Object} [options]
* @param {String|Array} options.url A string or array of URL(s) to video files
* @param {Array} options.coordinates lat,lng coordinates in order clockwise starting at the top left: tl, tr, br, bl
* @example
* var sourceObj = new mapboxgl.VideoSource({
* url: [
* 'https://www.mapbox.com/videos/baltimore-smoke.mp4',
* 'https://www.mapbox.com/videos/baltimore-smoke.webm'
* ],
* coordinates: [
* [39.18579907229748, -76.54335737228394],
* [39.1838364847587, -76.52803659439087],
* [39.17683392507606, -76.5295386314392],
* [39.17876344106642, -76.54520273208618]
* ]
* });
* map.addSource('some id', sourceObj); // add
* map.removeSource('some id'); // remove
*/
function VideoSource(options) {
this.coordinates = options.coordinates;
ajax.getVideo(options.url, function(err, video) {
// @TODO handle errors via event.
if (err) return;
this.video = video;
this.video.loop = true;
var loopID;
// start repainting when video starts playing
this.video.addEventListener('playing', function() {
loopID = this.map.style.animationLoop.set(Infinity);
this.map._rerender();
}.bind(this));
// stop repainting when video stops
this.video.addEventListener('pause', function() {
this.map.style.animationLoop.cancel(loopID);
}.bind(this));
this._loaded = true;
if (this.map) {
this.video.play();
this.createTile();
this.fire('change');
}
}.bind(this));
}
VideoSource.prototype = util.inherit(Evented, {
/**
* Return the HTML video element.
*
* @returns {Object}
*/
getVideo: function() {
return this.video;
},
onAdd: function(map) {
this.map = map;
if (this.video) {
this.video.play();
this.createTile();
}
},
createTile: function() {
/*
* Calculate which mercator tile is suitable for rendering the video in
* and create a buffer with the corner coordinates. These coordinates
* may be outside the tile, because raster tiles aren't clipped when rendering.
*/
var map = this.map;
var coords = this.coordinates.map(function(latlng) {
var loc = LatLng.convert(latlng);
return map.transform.locationCoordinate(loc).zoomTo(0);
});
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < coords.length; i++) {
minX = Math.min(minX, coords[i].column);
minY = Math.min(minY, coords[i].row);
maxX = Math.max(maxX, coords[i].column);
maxY = Math.max(maxY, coords[i].row);
}
var dx = maxX - minX;
var dy = maxY - minY;
var dMax = Math.max(dx, dy);
var center = new Coordinate((minX + maxX) / 2, (minY + maxY) / 2, 0)
.zoomTo(Math.floor(-Math.log(dMax) / Math.LN2));
var tileExtent = 4096;
var tileCoords = coords.map(function(coord) {
var zoomedCoord = coord.zoomTo(center.zoom);
return new Point(
Math.round((zoomedCoord.column - center.column) * tileExtent),
Math.round((zoomedCoord.row - center.row) * tileExtent));
});
var gl = map.painter.gl;
var maxInt16 = 32767;
var array = new Int16Array([
tileCoords[0].x, tileCoords[0].y, 0, 0,
tileCoords[1].x, tileCoords[1].y, maxInt16, 0,
tileCoords[3].x, tileCoords[3].y, 0, maxInt16,
tileCoords[2].x, tileCoords[2].y, maxInt16, maxInt16
]);
this.tile = new Tile();
this.tile.buckets = {};
this.tile.boundsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.tile.boundsBuffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
this.center = center;
},
loaded: function() {
return this.video && this.video.readyState >= 2;
},
update: function() {
// noop
},
render: function(layers, painter) {
if (!this._loaded) return;
if (this.video.readyState < 2) return; // not enough data for current position
var c = this.center;
this.tile.calculateMatrices(c.zoom, c.column, c.row, this.map.transform, painter);
var gl = painter.gl;
if (!this.tile.texture) {
this.tile.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.tile.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video);
} else {
gl.bindTexture(gl.TEXTURE_2D, this.tile.texture);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video);
}
painter.drawLayers(layers, this.tile.posMatrix, this.tile);
},
featuresAt: function(point, params, callback) {
return callback(null, []);
}
});
},{"../geo/coordinate":17,"../geo/lat_lng":18,"../util/ajax":84,"../util/evented":90,"../util/util":96,"./tile":40,"point-geometry":113}],45:[function(require,module,exports){
'use strict';
var Actor = require('../util/actor');
var WorkerTile = require('./worker_tile');
var util = require('../util/util');
var ajax = require('../util/ajax');
var vt = require('vector-tile');
var Protobuf = require('pbf');
var geojsonvt = require('geojson-vt');
var GeoJSONWrapper = require('./geojson_wrapper');
module.exports = function(self) {
return new Worker(self);
};
function Worker(self) {
this.self = self;
this.actor = new Actor(self, this);
this.loading = {};
this.loaded = {};
this.layers = [];
this.geoJSONIndexes = {};
}
util.extend(Worker.prototype, {
'set layers': function(layers) {
this.layers = layers;
},
'load tile': function(params, callback) {
var source = params.source,
uid = params.uid;
if (!this.loading[source])
this.loading[source] = {};
var tile = this.loading[source][uid] = new WorkerTile(params);
tile.xhr = ajax.getArrayBuffer(params.url, done.bind(this));
function done(err, data) {
delete this.loading[source][uid];
if (err) return callback(err);
tile.data = new vt.VectorTile(new Protobuf(new Uint8Array(data)));
tile.parse(tile.data, this.layers, this.actor, callback);
this.loaded[source] = this.loaded[source] || {};
this.loaded[source][uid] = tile;
}
},
'reload tile': function(params, callback) {
var loaded = this.loaded[params.source],
uid = params.uid;
if (loaded && loaded[uid]) {
var tile = loaded[uid];
tile.parse(tile.data, this.layers, this.actor, callback);
}
},
'abort tile': function(params) {
var loading = this.loading[params.source],
uid = params.uid;
if (loading && loading[uid]) {
loading[uid].xhr.abort();
delete loading[uid];
}
},
'remove tile': function(params) {
var loaded = this.loaded[params.source],
uid = params.uid;
if (loaded && loaded[uid]) {
delete loaded[uid];
}
},
'redo placement': function(params, callback) {
var loaded = this.loaded[params.source],
loading = this.loading[params.source],
uid = params.uid;
if (loaded && loaded[uid]) {
var tile = loaded[uid];
var result = tile.redoPlacement(params.angle, params.pitch, params.collisionDebug);
if (result.result) {
callback(null, result.result, result.transferables);
}
} else if (loading && loading[uid]) {
loading[uid].angle = params.angle;
}
},
'parse geojson': function(params, callback) {
var indexData = function(err, data) {
if (err) return callback(err);
this.geoJSONIndexes[params.source] = geojsonvt(data, {baseZoom: params.maxZoom});
callback(null);
}.bind(this);
// TODO accept params.url for urls instead
// Not, because of same origin issues, urls must either include an
// explicit origin or absolute path.
// ie: /foo/bar.json or http://example.com/bar.json
// but not ../foo/bar.json
if (typeof params.data === 'string') {
ajax.getJSON(params.data, indexData);
}
else indexData(null, params.data);
},
'load geojson tile': function(params, callback) {
var source = params.source,
coord = params.coord;
// console.time('tile ' + coord.z + ' ' + coord.x + ' ' + coord.y);
var geoJSONTile = this.geoJSONIndexes[source].getTile(coord.z, coord.x, coord.y);
// console.timeEnd('tile ' + coord.z + ' ' + coord.x + ' ' + coord.y);
// if (!geoJSONTile) console.log('not found', this.geoJSONIndexes[source], coord);
if (!geoJSONTile) return callback(null, null); // nothing in the given tile
var tile = new WorkerTile(params);
tile.parse(new GeoJSONWrapper(geoJSONTile.features), this.layers, this.actor, callback);
this.loaded[source] = this.loaded[source] || {};
this.loaded[source][params.uid] = tile;
},
'query features': function(params, callback) {
var tile = this.loaded[params.source] && this.loaded[params.source][params.uid];
if (tile) {
tile.featureTree.query(params, callback);
} else {
callback(null, []);
}
}
});
},{"../util/actor":83,"../util/ajax":84,"../util/util":96,"./geojson_wrapper":37,"./worker_tile":46,"geojson-vt":101,"pbf":111,"vector-tile":117}],46:[function(require,module,exports){
'use strict';
var FeatureTree = require('../data/feature_tree');
var Collision = require('../symbol/collision_tile');
var BufferSet = require('../data/buffer/buffer_set');
var createBucket = require('../data/create_bucket');
module.exports = WorkerTile;
function WorkerTile(params) {
this.coord = params.coord;
this.uid = params.uid;
this.zoom = params.zoom;
this.maxZoom = params.maxZoom;
this.tileSize = params.tileSize;
this.source = params.source;
this.overscaling = params.overscaling;
this.angle = params.angle;
this.pitch = params.pitch;
this.collisionDebug = params.collisionDebug;
this.stacks = {};
}
WorkerTile.prototype.parse = function(data, layers, actor, callback) {
this.status = 'parsing';
this.featureTree = new FeatureTree(this.coord, this.overscaling);
var i, k,
tile = this,
layer,
bucket,
buffers = new BufferSet(),
collision = this.collision = new Collision(this.zoom, 4096, this.tileSize),
buckets = {},
bucketsInOrder = this.bucketsInOrder = [],
bucketsBySourceLayer = {};
collision.reset(this.angle, this.pitch);
// Map non-ref layers to buckets.
for (i = 0; i < layers.length; i++) {
layer = layers[i];
if (layer.source !== this.source)
continue;
if (layer.ref)
continue;
var minzoom = layer.minzoom;
if (minzoom && this.zoom < minzoom && minzoom < this.maxZoom)
continue;
var maxzoom = layer.maxzoom;
if (maxzoom && this.zoom >= maxzoom)
continue;
var visibility = layer.layout.visibility;
if (visibility === 'none')
continue;
bucket = createBucket(layer, buffers, collision, this.zoom, this.overscaling, this.collisionDebug);
bucket.layers = [layer.id];
buckets[bucket.id] = bucket;
bucketsInOrder.push(bucket);
if (data.layers) {
// vectortile
var sourceLayer = layer['source-layer'];
if (!bucketsBySourceLayer[sourceLayer])
bucketsBySourceLayer[sourceLayer] = {};
bucketsBySourceLayer[sourceLayer][bucket.id] = bucket;
} else {
// geojson tile
bucketsBySourceLayer[bucket.id] = bucket;
}
}
// Index ref layers.
for (i = 0; i < layers.length; i++) {
layer = layers[i];
if (layer.source !== this.source)
continue;
if (!layer.ref)
continue;
bucket = buckets[layer.ref];
if (!bucket)
continue;
bucket.layers.push(layer.id);
}
var extent = 4096;
// read each layer, and sort its features into buckets
if (data.layers) {
// vectortile
for (k in bucketsBySourceLayer) {
layer = data.layers[k];
if (!layer) continue;
if (layer.extent) extent = layer.extent;
sortLayerIntoBuckets(layer, bucketsBySourceLayer[k]);
}
} else {
// geojson
sortLayerIntoBuckets(data, bucketsBySourceLayer);
}
function sortLayerIntoBuckets(layer, buckets) {
for (var i = 0; i < layer.length; i++) {
var feature = layer.feature(i);
for (var key in buckets) {
var bucket = buckets[key];
if (bucket.filter(feature)) {
bucket.features.push(feature);
}
}
}
}
var prevPlacementBucket;
var remaining = bucketsInOrder.length;
/*
* The async parsing here is a bit tricky.
* Some buckets depend on resources that may need to be loaded async (glyphs).
* Some buckets need to be parsed in order (to get collision priorities right).
*
* Dependencies calls are initiated first to get those rolling.
* Buckets that don't need to be parsed in order, aren't to save time.
*/
for (i = 0; i < bucketsInOrder.length; i++) {
bucket = bucketsInOrder[i];
// Link buckets that need to be parsed in order
if (bucket.collision) {
if (prevPlacementBucket) {
prevPlacementBucket.next = bucket;
} else {
bucket.previousPlaced = true;
}
prevPlacementBucket = bucket;
}
if (bucket.getDependencies) {
bucket.getDependencies(this, actor, dependenciesDone(bucket));
}
// immediately parse buckets where order doesn't matter and no dependencies
if (!bucket.collision && !bucket.getDependencies) {
parseBucket(tile, bucket);
}
}
function dependenciesDone(bucket) {
return function(err) {
bucket.dependenciesLoaded = true;
parseBucket(tile, bucket, err);
};
}
function parseBucket(tile, bucket, skip) {
if (bucket.getDependencies && !bucket.dependenciesLoaded) return;
if (bucket.collision && !bucket.previousPlaced) return;
if (!skip) {
var now = Date.now();
if (bucket.features.length) bucket.addFeatures();
var time = Date.now() - now;
if (bucket.interactive) {
for (var i = 0; i < bucket.features.length; i++) {
var feature = bucket.features[i];
tile.featureTree.insert(feature.bbox(), bucket.layers, feature);
}
}
if (typeof self !== 'undefined') {
self.bucketStats = self.bucketStats || {_total: 0};
self.bucketStats._total += time;
self.bucketStats[bucket.id] = (self.bucketStats[bucket.id] || 0) + time;
}
}
remaining--;
if (!remaining) {
done();
return;
}
// try parsing the next bucket, if it is ready
if (bucket.next) {
bucket.next.previousPlaced = true;
parseBucket(tile, bucket.next);
}
}
function done() {
tile.status = 'done';
if (tile.redoPlacementAfterDone) {
var result = tile.redoPlacement(tile.angle, tile.pitch).result;
buffers.glyphVertex = result.buffers.glyphVertex;
buffers.iconVertex = result.buffers.iconVertex;
buffers.collisionBoxVertex = result.buffers.collisionBoxVertex;
}
var transferables = [],
elementGroups = {};
for (k in buffers) {
transferables.push(buffers[k].array);
}
for (k in buckets) {
elementGroups[k] = buckets[k].elementGroups;
}
callback(null, {
elementGroups: elementGroups,
buffers: buffers,
extent: extent
}, transferables);
}
};
WorkerTile.prototype.redoPlacement = function(angle, pitch, collisionDebug) {
if (this.status !== 'done') {
this.redoPlacementAfterDone = true;
this.angle = angle;
return {};
}
var buffers = new BufferSet();
var transferables = [];
var elementGroups = {};
var collision = this.collision;
collision.reset(angle, pitch);
var bucketsInOrder = this.bucketsInOrder;
for (var i = 0; i < bucketsInOrder.length; i++) {
var bucket = bucketsInOrder[i];
if (bucket.type === 'symbol') {
bucket.placeFeatures(buffers, collisionDebug);
elementGroups[bucket.id] = bucket.elementGroups;
}
}
for (var k in buffers) {
transferables.push(buffers[k].array);
}
return {
result: {
elementGroups: elementGroups,
buffers: buffers
},
transferables: transferables
};
};
},{"../data/buffer/buffer_set":2,"../data/create_bucket":11,"../data/feature_tree":13,"../symbol/collision_tile":64}],47:[function(require,module,exports){
'use strict';
module.exports = AnimationLoop;
function AnimationLoop() {
this.n = 0;
this.times = [];
}
// Are all animations done?
AnimationLoop.prototype.stopped = function() {
this.times = this.times.filter(function(t) {
return t.time >= (new Date()).getTime();
});
return !this.times.length;
};
// Add a new animation that will run t milliseconds
// Returns an id that can be used to cancel it layer
AnimationLoop.prototype.set = function(t) {
this.times.push({ id: this.n, time: t + (new Date()).getTime() });
return this.n++;
};
// Cancel an animation
AnimationLoop.prototype.cancel = function(n) {
this.times = this.times.filter(function(t) {
return t.id !== n;
});
};
},{}],48:[function(require,module,exports){
'use strict';
var Evented = require('../util/evented');
var ajax = require('../util/ajax');
var browser = require('../util/browser');
module.exports = ImageSprite;
function ImageSprite(base) {
this.base = base;
this.retina = browser.devicePixelRatio > 1;
base = this.base + (this.retina ? '@2x' : '');
ajax.getJSON(base + '.json', function(err, data) {
if (err) {
this.fire('error', {error: err});
return;
}
this.data = data;
if (this.img) this.fire('load');
}.bind(this));
ajax.getImage(base + '.png', function(err, img) {
if (err) {
this.fire('error', {error: err});
return;
}
// premultiply the sprite
var data = img.getData();
var newdata = img.data = new Uint8Array(data.length);
for (var i = 0; i < data.length; i += 4) {
var alpha = data[i + 3] / 255;
newdata[i + 0] = data[i + 0] * alpha;
newdata[i + 1] = data[i + 1] * alpha;
newdata[i + 2] = data[i + 2] * alpha;
newdata[i + 3] = data[i + 3];
}
this.img = img;
if (this.data) this.fire('load');
}.bind(this));
}
ImageSprite.prototype = Object.create(Evented);
ImageSprite.prototype.toJSON = function() {
return this.base;
};
ImageSprite.prototype.loaded = function() {
return !!(this.data && this.img);
};
ImageSprite.prototype.resize = function(/*gl*/) {
if (browser.devicePixelRatio > 1 !== this.retina) {
var newSprite = new ImageSprite(this.base);
newSprite.on('load', function() {
this.img = newSprite.img;
this.data = newSprite.data;
this.retina = newSprite.retina;
}.bind(this));
}
};
function SpritePosition() {}
SpritePosition.prototype = { x: 0, y: 0, width: 0, height: 0, pixelRatio: 1, sdf: false };
ImageSprite.prototype.getSpritePosition = function(name) {
if (!this.loaded()) return new SpritePosition();
var pos = this.data && this.data[name];
if (pos && this.img) return pos;
return new SpritePosition();
};
},{"../util/ajax":84,"../util/browser":85,"../util/evented":90}],49:[function(require,module,exports){
'use strict';
var reference = require('./reference');
module.exports = {};
reference.layout.forEach(function(className) {
var Properties = function(props) {
for (var p in props) {
this[p] = props[p];
}
};
var properties = reference[className];
for (var prop in properties) {
if (properties[prop].default === undefined) continue;
Properties.prototype[prop] = properties[prop].default;
}
module.exports[className.replace('layout_', '')] = Properties;
});
},{"./reference":51}],50:[function(require,module,exports){
'use strict';
var reference = require('./reference');
var parseCSSColor = require('csscolorparser').parseCSSColor;
module.exports = {};
reference.paint.forEach(function(className) {
var Calculated = function() {};
var properties = reference[className];
for (var p in properties) {
var prop = properties[p],
value = prop.default;
if (value === undefined) continue;
if (prop.type === 'color') value = parseCSSColor(value);
Calculated.prototype[p] = value;
}
Calculated.prototype.hidden = false;
module.exports[className.replace('paint_', '')] = Calculated;
});
},{"./reference":51,"csscolorparser":97}],51:[function(require,module,exports){
module.exports = require('mapbox-gl-style-spec/reference/latest');
},{"mapbox-gl-style-spec/reference/latest":108}],52:[function(require,module,exports){
'use strict';
var Evented = require('../util/evented');
var Source = require('../source/source');
var StyleLayer = require('./style_layer');
var ImageSprite = require('./image_sprite');
var GlyphSource = require('../symbol/glyph_source');
var GlyphAtlas = require('../symbol/glyph_atlas');
var SpriteAtlas = require('../symbol/sprite_atlas');
var LineAtlas = require('../render/line_atlas');
var util = require('../util/util');
var ajax = require('../util/ajax');
var normalizeURL = require('../util/mapbox').normalizeStyleURL;
var browser = require('../util/browser');
var Dispatcher = require('../util/dispatcher');
var AnimationLoop = require('./animation_loop');
var validate = require('mapbox-gl-style-spec/lib/validate/latest');
module.exports = Style;
function Style(stylesheet, animationLoop) {
this.animationLoop = animationLoop || new AnimationLoop();
this.dispatcher = new Dispatcher(Math.max(browser.hardwareConcurrency - 1, 1), this);
this.glyphAtlas = new GlyphAtlas(1024, 1024);
this.spriteAtlas = new SpriteAtlas(512, 512);
this.spriteAtlas.resize(browser.devicePixelRatio);
this.lineAtlas = new LineAtlas(256, 512);
this._layers = {};
this._order = [];
this._groups = [];
this.sources = {};
this.zoomHistory = {};
util.bindAll([
'_forwardSourceEvent',
'_forwardTileEvent',
'_redoPlacement'
], this);
var loaded = function(err, stylesheet) {
if (err) {
this.fire('error', {error: err});
return;
}
var valid = validate(stylesheet);
if (valid.length) {
valid.forEach(function(e) {
throw new Error(e.message);
});
}
this._loaded = true;
this.stylesheet = stylesheet;
var sources = stylesheet.sources;
for (var id in sources) {
this.addSource(id, sources[id]);
}
if (stylesheet.sprite) {
this.sprite = new ImageSprite(stylesheet.sprite);
this.sprite.on('load', this.fire.bind(this, 'change'));
}
this.glyphSource = new GlyphSource(stylesheet.glyphs, this.glyphAtlas);
this._resolve();
this.fire('load');
}.bind(this);
if (typeof stylesheet === 'string') {
ajax.getJSON(normalizeURL(stylesheet), loaded);
} else {
browser.frame(loaded.bind(this, null, stylesheet));
}
}
Style.prototype = util.inherit(Evented, {
_loaded: false,
loaded: function() {
if (!this._loaded)
return false;
for (var id in this.sources)
if (!this.sources[id].loaded())
return false;
if (this.sprite && !this.sprite.loaded())
return false;
return true;
},
_resolve: function() {
var id, layer;
this._layers = {};
this._order = [];
for (var i = 0; i < this.stylesheet.layers.length; i++) {
layer = new StyleLayer(this.stylesheet.layers[i], this.stylesheet.constants || {});
this._layers[layer.id] = layer;
this._order.push(layer.id);
}
// Resolve layout properties.
for (id in this._layers) {
this._layers[id].resolveLayout();
}
// Resolve reference and paint properties.
for (id in this._layers) {
this._layers[id].resolveReference(this._layers);
this._layers[id].resolvePaint();
}
this._groupLayers();
this._broadcastLayers();
},
_groupLayers: function() {
var group;
this._groups = [];
// Split into groups of consecutive top-level layers with the same source.
for (var i = 0; i < this._order.length; ++i) {
var layer = this._layers[this._order[i]];
if (!group || layer.source !== group.source) {
group = [];
group.source = layer.source;
this._groups.push(group);
}
group.push(layer);
}
},
_broadcastLayers: function() {
var ordered = [];
for (var id in this._layers) {
ordered.push(this._layers[id].json());
}
this.dispatcher.broadcast('set layers', ordered);
},
_cascade: function(classes, options) {
if (!this._loaded) return;
options = options || {
transition: true
};
for (var id in this._layers) {
this._layers[id].cascade(classes, options,
this.stylesheet.transition || {},
this.animationLoop);
}
this.fire('change');
},
_recalculate: function(z) {
for (var id in this.sources)
this.sources[id].used = false;
this._updateZoomHistory(z);
this.rasterFadeDuration = 300;
for (id in this._layers) {
var layer = this._layers[id];
if (layer.recalculate(z, this.zoomHistory) && layer.source) {
this.sources[layer.source].used = true;
}
}
var maxZoomTransitionDuration = 300;
if (Math.floor(this.z) !== Math.floor(z)) {
this.animationLoop.set(maxZoomTransitionDuration);
}
this.z = z;
this.fire('zoom');
},
_updateZoomHistory: function(z) {
var zh = this.zoomHistory;
if (zh.lastIntegerZoom === undefined) {
// first time
zh.lastIntegerZoom = Math.floor(z);
zh.lastIntegerZoomTime = 0;
zh.lastZoom = z;
}
// check whether an integer zoom level as passed since the last frame
// and if yes, record it with the time. Used for transitioning patterns.
if (Math.floor(zh.lastZoom) < Math.floor(z)) {
zh.lastIntegerZoom = Math.floor(z);
zh.lastIntegerZoomTime = Date.now();
} else if (Math.floor(zh.lastZoom) > Math.floor(z)) {
zh.lastIntegerZoom = Math.floor(z + 1);
zh.lastIntegerZoomTime = Date.now();
}
zh.lastZoom = z;
},
addSource: function(id, source) {
if (this.sources[id] !== undefined) {
throw new Error('There is already a source with this ID');
}
source = Source.create(source);
this.sources[id] = source;
source.id = id;
source.style = this;
source.dispatcher = this.dispatcher;
source.glyphAtlas = this.glyphAtlas;
source
.on('load', this._forwardSourceEvent)
.on('error', this._forwardSourceEvent)
.on('change', this._forwardSourceEvent)
.on('tile.add', this._forwardTileEvent)
.on('tile.load', this._forwardTileEvent)
.on('tile.error', this._forwardTileEvent)
.on('tile.remove', this._forwardTileEvent);
this.fire('source.add', {source: source});
return this;
},
/**
* Remove a source from this stylesheet, given its id.
* @param {String} id id of the source to remove
* @returns {Style} this style
* @throws {Error} if no source is found with the given ID
* @private
*/
removeSource: function(id) {
if (this.sources[id] === undefined) {
throw new Error('There is no source with this ID');
}
var source = this.sources[id];
delete this.sources[id];
source
.off('load', this._forwardSourceEvent)
.off('error', this._forwardSourceEvent)
.off('change', this._forwardSourceEvent)
.off('tile.add', this._forwardTileEvent)
.off('tile.load', this._forwardTileEvent)
.off('tile.error', this._forwardTileEvent)
.off('tile.remove', this._forwardTileEvent);
this.fire('source.remove', {source: source});
return this;
},
/**
* Get a source by id.
* @param {String} id id of the desired source
* @returns {Object} source
* @private
*/
getSource: function(id) {
return this.sources[id];
},
/**
* Add a layer to the map style. The layer will be inserted before the layer with
* ID `before`, or appended if `before` is omitted.
* @param {StyleLayer|Object} layer
* @param {string=} before ID of an existing layer to insert before
* @fires layer.add
* @returns {Style} `this`
*/
addLayer: function(layer, before) {
if (this._layers[layer.id] !== undefined) {
throw new Error('There is already a layer with this ID');
}
if (!(layer instanceof StyleLayer)) {
layer = new StyleLayer(layer, this.stylesheet.constants || {});
}
this._layers[layer.id] = layer;
this._order.splice(before ? this._order.indexOf(before) : Infinity, 0, layer.id);
layer.resolveLayout();
layer.resolveReference(this._layers);
layer.resolvePaint();
this._groupLayers();
this._broadcastLayers();
this.fire('layer.add', {layer: layer});
return this;
},
/**
* Remove a layer from this stylesheet, given its id.
* @param {String} id id of the layer to remove
* @returns {Style} this style
* @throws {Error} if no layer is found with the given ID
* @private
*/
removeLayer: function(id) {
var layer = this._layers[id];
if (layer === undefined) {
throw new Error('There is no layer with this ID');
}
for (var i in this._layers) {
if (this._layers[i].ref === id) {
this.removeLayer(i);
}
}
delete this._layers[id];
this._order.splice(this._order.indexOf(id), 1);
this._groupLayers();
this._broadcastLayers();
this.fire('layer.remove', {layer: layer});
return this;
},
/**
* Get a layer by id.
* @param {String} id id of the desired layer
* @returns {Layer} layer
* @private
*/
getLayer: function(id) {
return this._layers[id];
},
/**
* If a layer has a `ref` property that makes it derive some values
* from another layer, return that referent layer. Otherwise,
* returns the layer itself.
* @param {String} id the layer's id
* @returns {Layer} the referent layer or the layer itself
* @private
*/
getReferentLayer: function(id) {
var layer = this.getLayer(id);
if (layer.ref) {
layer = this.getLayer(layer.ref);
}
return layer;
},
setFilter: function(layer, filter) {
layer = this.getReferentLayer(layer);
layer.filter = filter;
this._broadcastLayers();
this.sources[layer.source].reload();
},
/**
* Get a layer's filter object
* @param {String} layer the layer to inspect
* @returns {*} the layer's filter, if any
* @private
*/
getFilter: function(layer) {
return this.getReferentLayer(layer).filter;
},
setLayoutProperty: function(layer, name, value) {
layer = this.getReferentLayer(layer);
layer.setLayoutProperty(name, value);
this._broadcastLayers();
this.sources[layer.source].reload();
},
/**
* Get a layout property's value from a given layer
* @param {String} layer the layer to inspect
* @param {String} name the name of the layout property
* @returns {*} the property value
* @private
*/
getLayoutProperty: function(layer, name) {
return this.getReferentLayer(layer).getLayoutProperty(name);
},
setPaintProperty: function(layer, name, value, klass) {
this.getLayer(layer).setPaintProperty(name, value, klass);
},
getPaintProperty: function(layer, name, klass) {
return this.getLayer(layer).getPaintProperty(name, klass);
},
featuresAt: function(coord, params, callback) {
var features = [];
var error = null;
if (params.layer) {
params.layer = { id: params.layer };
}
util.asyncEach(Object.keys(this.sources), function(id, callback) {
var source = this.sources[id];
source.featuresAt(coord, params, function(err, result) {
if (result) features = features.concat(result);
if (err) error = err;
callback();
});
}.bind(this), function() {
if (error) return callback(error);
callback(null, features
.filter(function(feature) {
return this._layers[feature.layer] !== undefined;
}.bind(this))
.map(function(feature) {
feature.layer = this._layers[feature.layer].json();
return feature;
}.bind(this)));
}.bind(this));
},
_remove: function() {
this.dispatcher.remove();
},
_updateSources: function(transform) {
for (var id in this.sources) {
this.sources[id].update(transform);
}
},
_redoPlacement: function() {
for (var id in this.sources) {
if (this.sources[id].redoPlacement) this.sources[id].redoPlacement();
}
},
_forwardSourceEvent: function(e) {
this.fire('source.' + e.type, util.extend({source: e.target}, e));
},
_forwardTileEvent: function(e) {
this.fire(e.type, util.extend({source: e.target}, e));
},
// Callbacks from web workers
'get sprite json': function(params, callback) {
var sprite = this.sprite;
if (sprite.loaded()) {
callback(null, { sprite: sprite.data, retina: sprite.retina });
} else {
sprite.on('load', function() {
callback(null, { sprite: sprite.data, retina: sprite.retina });
});
}
},
'get icons': function(params, callback) {
var sprite = this.sprite;
var spriteAtlas = this.spriteAtlas;
if (sprite.loaded()) {
spriteAtlas.setSprite(sprite);
spriteAtlas.addIcons(params.icons, callback);
} else {
sprite.on('load', function() {
spriteAtlas.setSprite(sprite);
spriteAtlas.addIcons(params.icons, callback);
});
}
},
'get glyphs': function(params, callback) {
this.glyphSource.getSimpleGlyphs(params.fontstack, params.codepoints, params.uid, callback);
}
});
},{"../render/line_atlas":33,"../source/source":39,"../symbol/glyph_atlas":66,"../symbol/glyph_source":67,"../symbol/sprite_atlas":73,"../util/ajax":84,"../util/browser":85,"../util/dispatcher":87,"../util/evented":90,"../util/mapbox":93,"../util/util":96,"./animation_loop":47,"./image_sprite":48,"./style_layer":56,"mapbox-gl-style-spec/lib/validate/latest":106}],53:[function(require,module,exports){
'use strict';
var util = require('../util/util');
exports.resolve = function(value, constants) {
function resolve(value) {
return typeof value === 'string' && value[0] === '@' ? constants[value] : value;
}
var i;
value = resolve(value);
if (Array.isArray(value)) {
value = value.slice();
for (i = 0; i < value.length; i++) {
if (value[i] in constants) {
value[i] = resolve(value[i]);
}
}
}
if (value.stops) {
value = util.extend({}, value);
value.stops = value.stops.slice();
for (i = 0; i < value.stops.length; i++) {
if (value.stops[i][1] in constants) {
value.stops[i] = [
value.stops[i][0],
resolve(value.stops[i][1])
];
}
}
}
return value;
};
exports.resolveAll = function (properties, constants) {
if (!constants)
return properties;
var result = {};
for (var key in properties) {
result[key] = exports.resolve(properties[key], constants);
}
return result;
};
},{"../util/util":96}],54:[function(require,module,exports){
'use strict';
var parseCSSColor = require('csscolorparser').parseCSSColor;
var mapboxGLFunction = require('mapbox-gl-function');
var util = require('../util/util');
module.exports = StyleDeclaration;
function StyleDeclaration(reference, value) {
this.type = reference.type;
this.transitionable = reference.transition;
// immutable representation of value. used for comparison
this.json = JSON.stringify(value);
if (this.type !== 'color') {
this.value = value;
} else if (value.stops) {
this.value = prepareColorFunction(value);
} else {
this.value = parseColor(value);
}
if (reference.function === 'interpolated') {
this.calculate = mapboxGLFunction.interpolated(this.value);
} else {
this.calculate = mapboxGLFunction['piecewise-constant'](this.value);
if (reference.transition) {
this.calculate = transitioned(this.calculate);
}
}
}
function transitioned(calculate) {
return function(z, zh, duration) {
var fraction = z % 1;
var t = Math.min((Date.now() - zh.lastIntegerZoomTime) / duration, 1);
var fromScale = 1;
var toScale = 1;
var mix, from, to;
if (z > zh.lastIntegerZoom) {
mix = fraction + (1 - fraction) * t;
fromScale *= 2;
from = calculate(z - 1);
to = calculate(z);
} else {
mix = 1 - (1 - t) * fraction;
to = calculate(z);
from = calculate(z + 1);
fromScale /= 2;
}
return {
from: from,
fromScale: fromScale,
to: to,
toScale: toScale,
t: mix
};
};
}
var colorCache = {};
function parseColor(value) {
if (colorCache[value]) return colorCache[value];
var color = prepareColor(parseCSSColor(value));
colorCache[value] = color;
return color;
}
function prepareColor(c) {
return [c[0] / 255, c[1] / 255, c[2] / 255, c[3] / 1];
}
function prepareColorFunction(f) {
return util.extend({}, f, {stops: f.stops.map(function(stop) {
return [stop[0], parseColor(stop[1])];
})});
}
},{"../util/util":96,"csscolorparser":97,"mapbox-gl-function":105}],55:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var reference = require('./reference');
var StyleConstant = require('./style_constant');
var StyleDeclaration = require('./style_declaration');
var lookup = {
paint: {},
layout: {}
};
reference.layer.type.values.forEach(function(type) {
lookup.paint[type] = makeConstructor(reference['paint_' + type]);
lookup.layout[type] = makeConstructor(reference['layout_' + type]);
});
function makeConstructor(reference) {
function StyleDeclarationSet(properties, constants) {
this._values = {};
this._transitions = {};
this._constants = constants;
for (var k in properties) {
this[k] = StyleConstant.resolve(properties[k], this._constants);
}
}
Object.keys(reference).forEach(function(k) {
var property = reference[k];
Object.defineProperty(StyleDeclarationSet.prototype, k, {
set: function(v) {
this._values[k] = new StyleDeclaration(property, StyleConstant.resolve(v, this._constants));
},
get: function() {
return this._values[k].value;
}
});
if (property.transition) {
Object.defineProperty(StyleDeclarationSet.prototype, k + '-transition', {
set: function(v) {
this._transitions[k] = v;
},
get: function() {
return this._transitions[k];
}
});
}
});
StyleDeclarationSet.prototype.values = function() {
return this._values;
};
StyleDeclarationSet.prototype.transition = function(k, global) {
var t = this._transitions[k] || {};
return {
duration: util.coalesce(t.duration, global.duration, 300),
delay: util.coalesce(t.delay, global.delay, 0)
};
};
StyleDeclarationSet.prototype.json = function() {
var result = {};
for (var v in this._values) {
result[v] = this._values[v].value;
}
for (var t in this._transitions) {
result[t + '-transition'] = this._transitions[v];
}
return result;
};
return StyleDeclarationSet;
}
module.exports = function(renderType, layerType, properties, constants) {
return new lookup[renderType][layerType](properties, constants);
};
},{"../util/util":96,"./reference":51,"./style_constant":53,"./style_declaration":54}],56:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var StyleConstant = require('./style_constant');
var StyleTransition = require('./style_transition');
var StyleDeclarationSet = require('./style_declaration_set');
var LayoutProperties = require('./layout_properties');
var PaintProperties = require('./paint_properties');
module.exports = StyleLayer;
function StyleLayer(layer, constants) {
this._layer = layer;
this._constants = constants;
this.id = layer.id;
this.ref = layer.ref;
// Resolved and cascaded paint properties.
this._resolved = {}; // class name -> StyleDeclarationSet
this._cascaded = {}; // property name -> StyleTransition
this.assign(layer);
}
StyleLayer.prototype = {
resolveLayout: function() {
if (!this.ref) {
this.layout = new LayoutProperties[this.type](
StyleConstant.resolveAll(this._layer.layout, this._constants));
if (this.layout['symbol-placement'] === 'line') {
if (!this.layout.hasOwnProperty('text-rotation-alignment')) {
this.layout['text-rotation-alignment'] = 'map';
}
if (!this.layout.hasOwnProperty('icon-rotation-alignment')) {
this.layout['icon-rotation-alignment'] = 'map';
}
this.layout['symbol-avoid-edges'] = true;
}
}
},
setLayoutProperty: function(name, value) {
this.layout[name] = StyleConstant.resolve(value, this._constants);
},
getLayoutProperty: function(name) {
return this.layout[name];
},
resolveReference: function(layers) {
if (this.ref) {
this.assign(layers[this.ref]);
}
},
resolvePaint: function() {
for (var p in this._layer) {
var match = p.match(/^paint(?:\.(.*))?$/);
if (!match)
continue;
this._resolved[match[1] || ''] =
new StyleDeclarationSet('paint', this.type, this._layer[p], this._constants);
}
},
setPaintProperty: function(name, value, klass) {
var declarations = this._resolved[klass || ''];
if (!declarations) {
declarations = this._resolved[klass || ''] =
new StyleDeclarationSet('paint', this.type, {}, this._constants);
}
declarations[name] = value;
},
getPaintProperty: function(name, klass) {
var declarations = this._resolved[klass || ''];
if (!declarations)
return undefined;
return declarations[name];
},
cascade: function(classes, options, globalTrans, animationLoop) {
for (var klass in this._resolved) {
if (klass !== "" && !classes[klass])
continue;
var declarations = this._resolved[klass],
values = declarations.values();
for (var k in values) {
var newDeclaration = values[k];
var oldTransition = options.transition ? this._cascaded[k] : undefined;
// Only create a new transition if the declaration changed
if (!oldTransition || oldTransition.declaration.json !== newDeclaration.json) {
var newStyleTrans = declarations.transition(k, globalTrans);
var newTransition = this._cascaded[k] =
new StyleTransition(newDeclaration, oldTransition, newStyleTrans);
// Run the animation loop until the end of the transition
if (!newTransition.instant()) {
newTransition.loopID = animationLoop.set(newTransition.endTime - (new Date()).getTime());
}
if (oldTransition) {
animationLoop.cancel(oldTransition.loopID);
}
}
}
}
},
recalculate: function(z, zoomHistory) {
var type = this.type,
calculated = this.paint = new PaintProperties[type]();
for (var k in this._cascaded) {
calculated[k] = this._cascaded[k].at(z, zoomHistory);
}
this.hidden = (this.minzoom && z < this.minzoom) ||
(this.maxzoom && z >= this.maxzoom) ||
// include visibility check for non-bucketed background layers
(this.layout.visibility === 'none');
if (type === 'symbol') {
if ((calculated['text-opacity'] === 0 || !this.layout['text-field']) &&
(calculated['icon-opacity'] === 0 || !this.layout['icon-image'])) {
this.hidden = true;
} else {
premultiplyLayer(calculated, 'text');
premultiplyLayer(calculated, 'icon');
}
} else if (calculated[type + '-opacity'] === 0) {
this.hidden = true;
} else {
premultiplyLayer(calculated, type);
}
if (this._cascaded['line-dasharray']) {
// If the line is dashed, scale the dash lengths by the line
// width at the previous round zoom level.
var dashArray = calculated['line-dasharray'];
var lineWidth = this._cascaded['line-width'] ?
this._cascaded['line-width'].at(Math.floor(z), Infinity) :
calculated['line-width'];
dashArray.fromScale *= lineWidth;
dashArray.toScale *= lineWidth;
}
return !this.hidden;
},
assign: function(layer) {
util.extend(this, util.pick(layer,
['type', 'source', 'source-layer',
'minzoom', 'maxzoom', 'filter',
'layout']));
},
json: function() {
return util.extend({},
this._layer,
util.pick(this,
['type', 'source', 'source-layer',
'minzoom', 'maxzoom', 'filter',
'layout', 'paint']));
}
};
function premultiplyLayer(layer, type) {
var colorProp = type + '-color',
haloProp = type + '-halo-color',
outlineProp = type + '-outline-color',
color = layer[colorProp],
haloColor = layer[haloProp],
outlineColor = layer[outlineProp],
opacity = layer[type + '-opacity'];
var colorOpacity = color && (opacity * color[3]);
var haloOpacity = haloColor && (opacity * haloColor[3]);
var outlineOpacity = outlineColor && (opacity * outlineColor[3]);
if (colorOpacity !== undefined && colorOpacity < 1) {
layer[colorProp] = util.premultiply([color[0], color[1], color[2], colorOpacity]);
}
if (haloOpacity !== undefined && haloOpacity < 1) {
layer[haloProp] = util.premultiply([haloColor[0], haloColor[1], haloColor[2], haloOpacity]);
}
if (outlineOpacity !== undefined && outlineOpacity < 1) {
layer[outlineProp] = util.premultiply([outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity]);
}
}
},{"../util/util":96,"./layout_properties":49,"./paint_properties":50,"./style_constant":53,"./style_declaration_set":55,"./style_transition":57}],57:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var interpolate = require('../util/interpolate');
module.exports = StyleTransition;
/*
* Represents a transition between two declarations
*/
function StyleTransition(declaration, oldTransition, value) {
this.declaration = declaration;
this.startTime = this.endTime = (new Date()).getTime();
var type = declaration.type;
if ((type === 'string' || type === 'array') && declaration.transitionable) {
this.interp = interpZoomTransitioned;
} else {
this.interp = interpolate[type];
}
this.oldTransition = oldTransition;
this.duration = value.duration || 0;
this.delay = value.delay || 0;
if (!this.instant()) {
this.endTime = this.startTime + this.duration + this.delay;
this.ease = util.easeCubicInOut;
}
if (oldTransition && oldTransition.endTime <= this.startTime) {
// Old transition is done running, so we can
// delete its reference to its old transition.
delete oldTransition.oldTransition;
}
}
StyleTransition.prototype.instant = function() {
return !this.oldTransition || !this.interp || (this.duration === 0 && this.delay === 0);
};
/*
* Return the value of the transitioning property at zoom level `z` and optional time `t`
*/
StyleTransition.prototype.at = function(z, zoomHistory, t) {
var value = this.declaration.calculate(z, zoomHistory, this.duration);
if (this.instant()) return value;
t = t || Date.now();
if (t < this.endTime) {
var oldValue = this.oldTransition.at(z, zoomHistory, this.startTime);
var eased = this.ease((t - this.startTime - this.delay) / this.duration);
value = this.interp(oldValue, value, eased);
}
return value;
};
function interpZoomTransitioned(from, to, t) {
return {
from: from.to,
fromScale: from.toScale,
to: to.to,
toScale: to.toScale,
t: t
};
}
},{"../util/interpolate":92,"../util/util":96}],58:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
module.exports = Anchor;
function Anchor(x, y, angle, segment) {
this.x = x;
this.y = y;
this.angle = angle;
if (segment !== undefined) {
this.segment = segment;
}
}
Anchor.prototype = Object.create(Point.prototype);
Anchor.prototype.clone = function() {
return new Anchor(this.x, this.y, this.angle, this.segment);
};
},{"point-geometry":113}],59:[function(require,module,exports){
'use strict';
module.exports = BinPack;
function BinPack(width, height) {
this.width = width;
this.height = height;
this.free = [{ x: 0, y: 0, w: width, h: height }];
}
/**
* Simple algorithm to recursively merge the newly released cell with its
* neighbor. This doesn't merge more than two cells at a time, and fails
* for complicated merges.
* @private
*/
BinPack.prototype.release = function(rect) {
for (var i = 0; i < this.free.length; i++) {
var free = this.free[i];
if (free.y === rect.y && free.h === rect.h && free.x + free.w === rect.x) {
free.w += rect.w;
} else if (free.x === rect.x && free.w === rect.w && free.y + free.h === rect.y) {
free.h += rect.h;
} else if (rect.y === free.y && rect.h === free.h && rect.x + rect.w === free.x) {
free.x = rect.x;
free.w += rect.w;
} else if (rect.x === free.x && rect.w === free.w && rect.y + rect.h === free.y) {
free.y = rect.y;
free.h += rect.h;
} else continue;
this.free.splice(i, 1);
this.release(free);
return;
}
this.free.push(rect);
};
BinPack.prototype.allocate = function(width, height) {
// Find the smallest free rect angle
var rect = { x: Infinity, y: Infinity, w: Infinity, h: Infinity };
var smallest = -1;
for (var i = 0; i < this.free.length; i++) {
var ref = this.free[i];
if (width <= ref.w && height <= ref.h && ref.y <= rect.y && ref.x <= rect.x) {
rect = ref;
smallest = i;
}
}
if (smallest < 0) {
// There's no space left for this char.
return { x: -1, y: -1 };
}
this.free.splice(smallest, 1);
// Shorter/Longer Axis Split Rule (SAS)
// http://clb.demon.fi/files/RectangleBinPack.pdf p. 15
// Ignore the dimension of R and just split long the shorter dimension
// See Also: http://www.cs.princeton.edu/~chazelle/pubs/blbinpacking.pdf
if (rect.w < rect.h) {
// split horizontally
// +--+---+
// |__|___| <-- b1
// +------+ <-- b2
if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: height });
if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: rect.w, h: rect.h - height });
} else {
// split vertically
// +--+---+
// |__| | <-- b1
// +--|---+ <-- b2
if (rect.w > width) this.free.push({ x: rect.x + width, y: rect.y, w: rect.w - width, h: rect.h });
if (rect.h > height) this.free.push({ x: rect.x, y: rect.y + height, w: width, h: rect.h - height });
}
return { x: rect.x, y: rect.y, w: width, h: height };
};
},{}],60:[function(require,module,exports){
'use strict';
module.exports = checkMaxAngle;
function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
// horizontal labels always pass
if (anchor.segment === undefined) return true;
var p = anchor;
var index = anchor.segment + 1;
var anchorDistance = 0;
// move backwards along the line to the first segment the label appears on
while (anchorDistance > -labelLength / 2) {
index--;
// there isn't enough room for the label after the beginning of the line
if (index < 0) return false;
anchorDistance -= line[index].dist(p);
p = line[index];
}
anchorDistance += line[index].dist(line[index + 1]);
index++;
// store recent corners and their total angle difference
var recentCorners = [];
var recentAngleDelta = 0;
// move forwards by the length of the label and check angles along the way
while (anchorDistance < labelLength / 2) {
var prev = line[index - 1];
var current = line[index];
var next = line[index + 1];
// there isn't enough room for the label before the end of the line
if (!next) return false;
var angleDelta = prev.angleTo(current) - current.angleTo(next);
// restrict angle to -pi..pi range
angleDelta = ((angleDelta + 3 * Math.PI) % (Math.PI * 2)) - Math.PI;
recentCorners.push({
distance: anchorDistance,
angleDelta: angleDelta
});
recentAngleDelta += angleDelta;
// remove corners that are far enough away from the list of recent anchors
while (anchorDistance - recentCorners[0].distance > windowSize) {
recentAngleDelta -= recentCorners.shift().angleDelta;
}
// the sum of angles within the window area exceeds the maximum allowed value. check fails.
if (Math.abs(recentAngleDelta) > maxAngle) return false;
index++;
anchorDistance += current.dist(next);
}
// no part of the line had an angle greater than the maximum allowed. check passes.
return true;
}
},{}],61:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
module.exports = clipLine;
function clipLine(lines, x1, y1, x2, y2) {
var clippedLines = [];
for (var l = 0; l < lines.length; l++) {
var line = lines[l];
var clippedLine;
for (var i = 0; i < line.length - 1; i++) {
var p0 = line[i];
var p1 = line[i + 1];
if (p0.x < x1 && p1.x < x1) {
continue;
} else if (p0.x < x1) {
p0 = new Point(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x)));
} else if (p1.x < x1) {
p1 = new Point(x1, p0.y + (p1.y - p0.y) * ((x1 - p0.x) / (p1.x - p0.x)));
}
if (p0.y < y1 && p1.y < y1) {
continue;
} else if (p0.y < y1) {
p0 = new Point(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1);
} else if (p1.y < y1) {
p1 = new Point(p0.x + (p1.x - p0.x) * ((y1 - p0.y) / (p1.y - p0.y)), y1);
}
if (p0.x >= x2 && p1.x >= x2) {
continue;
} else if (p0.x >= x2) {
p0 = new Point(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x)));
} else if (p1.x >= x2) {
p1 = new Point(x2, p0.y + (p1.y - p0.y) * ((x2 - p0.x) / (p1.x - p0.x)));
}
if (p0.y >= y2 && p1.y >= y2) {
continue;
} else if (p0.y >= y2) {
p0 = new Point(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2);
} else if (p1.y >= y2) {
p1 = new Point(p0.x + (p1.x - p0.x) * ((y2 - p0.y) / (p1.y - p0.y)), y2);
}
if (!clippedLine || !p0.equals(clippedLine[clippedLine.length - 1])) {
clippedLine = [p0];
clippedLines.push(clippedLine);
}
clippedLine.push(p1);
}
}
return clippedLines;
}
},{"point-geometry":113}],62:[function(require,module,exports){
'use strict';
module.exports = CollisionBox;
function CollisionBox(anchor, x1, y1, x2, y2, maxScale) {
// the box is centered around the anchor point
this.anchor = anchor;
// distances to the edges from the anchor
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
// the box is only valid for scales < maxScale.
// The box does not block other boxes at scales >= maxScale;
this.maxScale = maxScale;
// the scale at which the label can first be shown
this.placementScale = 0;
// rotated and scaled bbox used for indexing
this[0] = this[1] = this[2] = this[3] = 0;
}
},{}],63:[function(require,module,exports){
'use strict';
var CollisionBox = require('./collision_box');
module.exports = CollisionFeature;
function CollisionFeature(line, anchor, shaped, boxScale, padding, alignLine) {
var y1 = shaped.top * boxScale - padding;
var y2 = shaped.bottom * boxScale + padding;
var x1 = shaped.left * boxScale - padding;
var x2 = shaped.right * boxScale + padding;
this.boxes = [];
if (alignLine) {
var height = y2 - y1;
var length = x2 - x1;
if (height <= 0) return;
// set minimum box height to avoid very many small labels
height = Math.max(10 * boxScale, height);
this.bboxifyLabel(line, anchor, length, height);
} else {
this.boxes.push(new CollisionBox(anchor, x1, y1, x2, y2, Infinity));
}
}
CollisionFeature.prototype.bboxifyLabel = function(line, anchor, labelLength, boxSize) {
var step = boxSize / 2;
var nBoxes = Math.floor(labelLength / step);
// offset the center of the first box by half a box so that the edge of the
// box is at the edge of the label.
var firstBoxOffset = -boxSize / 2;
var bboxes = this.boxes;
var p = anchor;
var index = anchor.segment + 1;
var anchorDistance = firstBoxOffset;
// move backwards along the line to the first segment the label appears on
do {
index--;
// there isn't enough room for the label after the beginning of the line
// checkMaxAngle should have already caught this
if (index < 0) return bboxes;
anchorDistance -= line[index].dist(p);
p = line[index];
} while (anchorDistance > -labelLength / 2);
var segmentLength = line[index].dist(line[index + 1]);
for (var i = 0; i < nBoxes; i++) {
// the distance the box will be from the anchor
var boxDistanceToAnchor = -labelLength / 2 + i * step;
// the box is not on the current segment. Move to the next segment.
while (anchorDistance + segmentLength < boxDistanceToAnchor) {
anchorDistance += segmentLength;
index++;
// There isn't enough room before the end of the line.
if (index + 1 >= line.length) return bboxes;
segmentLength = line[index].dist(line[index + 1]);
}
// the distance the box will be from the beginning of the segment
var segmentBoxDistance = boxDistanceToAnchor - anchorDistance;
var p0 = line[index];
var p1 = line[index + 1];
var boxAnchor = p1.sub(p0)._unit()._mult(segmentBoxDistance)._add(p0);
var distanceToInnerEdge = Math.max(Math.abs(boxDistanceToAnchor - firstBoxOffset) - step / 2, 0);
var maxScale = labelLength / 2 / distanceToInnerEdge;
bboxes.push(new CollisionBox(boxAnchor, -boxSize / 2, -boxSize / 2, boxSize / 2, boxSize / 2, maxScale));
}
return bboxes;
};
},{"./collision_box":62}],64:[function(require,module,exports){
'use strict';
var rbush = require('rbush');
module.exports = CollisionTile;
function CollisionTile(zoom, tileExtent, tileSize) {
this.zoom = zoom;
this.tilePixelRatio = tileExtent / tileSize;
}
CollisionTile.prototype.minScale = 0.25;
CollisionTile.prototype.maxScale = 2;
CollisionTile.prototype.reset = function(angle, pitch) {
this.tree = rbush();
this.angle = angle;
var sin = Math.sin(angle),
cos = Math.cos(angle);
this.rotationMatrix = [cos, -sin, sin, cos];
// Stretch boxes in y direction to account for the map tilt.
this.yStretch = 1 / Math.cos(pitch / 180 * Math.PI);
// The amount the map is squished depends on the y position.
// Sort of account for this by making all boxes a bit bigger.
this.yStretch = Math.pow(this.yStretch, 1.3);
};
CollisionTile.prototype.placeFeature = function(feature) {
var minPlacementScale = this.minScale;
var rotationMatrix = this.rotationMatrix;
var yStretch = this.yStretch;
for (var b = 0; b < feature.boxes.length; b++) {
var box = feature.boxes[b];
var anchor = box.anchor.matMult(rotationMatrix);
var x = anchor.x;
var y = anchor.y;
box[0] = x + box.x1;
box[1] = y + box.y1 * yStretch;
box[2] = x + box.x2;
box[3] = y + box.y2 * yStretch;
var blockingBoxes = this.tree.search(box);
for (var i = 0; i < blockingBoxes.length; i++) {
var blocking = blockingBoxes[i];
var blockingAnchor = blocking.anchor.matMult(rotationMatrix);
// Find the lowest scale at which the two boxes can fit side by side without overlapping.
// Original algorithm:
var s1 = (blocking.x1 - box.x2) / (x - blockingAnchor.x); // scale at which new box is to the left of old box
var s2 = (blocking.x2 - box.x1) / (x - blockingAnchor.x); // scale at which new box is to the right of old box
var s3 = (blocking.y1 - box.y2) * yStretch / (y - blockingAnchor.y); // scale at which new box is to the top of old box
var s4 = (blocking.y2 - box.y1) * yStretch / (y - blockingAnchor.y); // scale at which new box is to the bottom of old box
if (isNaN(s1) || isNaN(s2)) s1 = s2 = 1;
if (isNaN(s3) || isNaN(s4)) s3 = s4 = 1;
var collisionFreeScale = Math.min(Math.max(s1, s2), Math.max(s3, s4));
if (collisionFreeScale > blocking.maxScale) {
// After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it,
// so unblock the new box at the scale that the old box disappears.
collisionFreeScale = blocking.maxScale;
}
if (collisionFreeScale > box.maxScale) {
// If the box can only be shown after it is visible, then the box can never be shown.
// But the label can be shown after this box is not visible.
collisionFreeScale = box.maxScale;
}
if (collisionFreeScale > minPlacementScale &&
collisionFreeScale >= blocking.placementScale) {
// If this collision occurs at a lower scale than previously found collisions
// and the collision occurs while the other label is visible
// this this is the lowest scale at which the label won't collide with anything
minPlacementScale = collisionFreeScale;
}
if (minPlacementScale >= this.maxScale) return minPlacementScale;
}
}
return minPlacementScale;
};
CollisionTile.prototype.insertFeature = function(feature, minPlacementScale) {
var boxes = feature.boxes;
for (var k = 0; k < boxes.length; k++) {
boxes[k].placementScale = minPlacementScale;
}
if (minPlacementScale < this.maxScale) {
this.tree.load(boxes);
}
};
},{"rbush":114}],65:[function(require,module,exports){
'use strict';
var interpolate = require('../util/interpolate');
var Anchor = require('../symbol/anchor');
var checkMaxAngle = require('./check_max_angle');
module.exports = getAnchors;
function getAnchors(line, spacing, maxAngle, shapedText, glyphSize, boxScale, overscaling) {
// Resample a line to get anchor points for labels and check that each
// potential label passes text-max-angle check and has enough froom to fit
// on the line.
var angleWindowSize = shapedText ?
3 / 5 * glyphSize * boxScale :
0;
// Offset the first anchor by half the label length (or half the spacing distance for icons).
// Add a bit of extra offset to avoid collisions at T intersections.
var labelLength = shapedText ? shapedText.right - shapedText.left : spacing;
var extraOffset = glyphSize * 2;
var offset = ((labelLength / 2 + extraOffset) * boxScale * overscaling) % spacing;
return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength * boxScale, false);
}
function resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength, placeAtMiddle) {
var distance = 0,
markedDistance = offset ? offset - spacing : 0;
var anchors = [];
for (var i = 0; i < line.length - 1; i++) {
var a = line[i],
b = line[i + 1];
var segmentDist = a.dist(b),
angle = b.angleTo(a);
while (markedDistance + spacing < distance + segmentDist) {
markedDistance += spacing;
var t = (markedDistance - distance) / segmentDist,
x = interpolate(a.x, b.x, t),
y = interpolate(a.y, b.y, t);
if (x >= 0 && x < 4096 && y >= 0 && y < 4096) {
x = Math.round(x);
y = Math.round(y);
var anchor = new Anchor(x, y, angle, i);
if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
anchors.push(anchor);
}
}
}
distance += segmentDist;
}
if (!placeAtMiddle && !anchors.length) {
// The first attempt at finding anchors at which labels can be placed failed.
// Try again, but this time just try placing one anchor at the middle of the line.
// This has the most effect for short lines in overscaled tiles, since the
// initial offset used in overscaled tiles is calculated to align labels with positions in
// parent tiles instead of placing the label as close to the beginning as possible.
anchors = resample(line, distance / 2, spacing, angleWindowSize, maxAngle, labelLength, true);
}
return anchors;
}
},{"../symbol/anchor":58,"../util/interpolate":92,"./check_max_angle":60}],66:[function(require,module,exports){
'use strict';
var BinPack = require('./bin_pack');
module.exports = GlyphAtlas;
function GlyphAtlas(width, height) {
this.width = width;
this.height = height;
this.bin = new BinPack(width, height);
this.index = {};
this.ids = {};
this.data = new Uint8Array(width * height);
}
GlyphAtlas.prototype = {
get debug() {
return 'canvas' in this;
},
set debug(value) {
if (value && !this.canvas) {
this.canvas = document.createElement('canvas');
this.canvas.width = this.width;
this.canvas.height = this.height;
document.body.appendChild(this.canvas);
this.ctx = this.canvas.getContext('2d');
} else if (!value && this.canvas) {
this.canvas.parentNode.removeChild(this.canvas);
delete this.ctx;
delete this.canvas;
}
}
};
GlyphAtlas.prototype.getGlyphs = function() {
var glyphs = {},
split,
name,
id;
for (var key in this.ids) {
split = key.split('#');
name = split[0];
id = split[1];
if (!glyphs[name]) glyphs[name] = [];
glyphs[name].push(id);
}
return glyphs;
};
GlyphAtlas.prototype.getRects = function() {
var rects = {},
split,
name,
id;
for (var key in this.ids) {
split = key.split('#');
name = split[0];
id = split[1];
if (!rects[name]) rects[name] = {};
rects[name][id] = this.index[key];
}
return rects;
};
GlyphAtlas.prototype.removeGlyphs = function(id) {
for (var key in this.ids) {
var ids = this.ids[key];
var pos = ids.indexOf(id);
if (pos >= 0) ids.splice(pos, 1);
this.ids[key] = ids;
if (!ids.length) {
var rect = this.index[key];
var target = this.data;
for (var y = 0; y < rect.h; y++) {
var y1 = this.width * (rect.y + y) + rect.x;
for (var x = 0; x < rect.w; x++) {
target[y1 + x] = 0;
}
}
this.dirty = true;
this.bin.release(rect);
delete this.index[key];
delete this.ids[key];
}
}
this.updateTexture(this.gl);
};
GlyphAtlas.prototype.addGlyph = function(id, name, glyph, buffer) {
if (!glyph) {
// console.warn('missing glyph', code, String.fromCharCode(code));
return null;
}
var key = name + "#" + glyph.id;
// The glyph is already in this texture.
if (this.index[key]) {
if (this.ids[key].indexOf(id) < 0) {
this.ids[key].push(id);
}
return this.index[key];
}
// The glyph bitmap has zero width.
if (!glyph.bitmap) {
return null;
}
var bufferedWidth = glyph.width + buffer * 2;
var bufferedHeight = glyph.height + buffer * 2;
// Add a 1px border around every image.
var padding = 1;
var packWidth = bufferedWidth + 2 * padding;
var packHeight = bufferedHeight + 2 * padding;
// Increase to next number divisible by 4, but at least 1.
// This is so we can scale down the texture coordinates and pack them
// into 2 bytes rather than 4 bytes.
packWidth += (4 - packWidth % 4);
packHeight += (4 - packHeight % 4);
var rect = this.bin.allocate(packWidth, packHeight);
if (rect.x < 0) {
console.warn('glyph bitmap overflow');
return { glyph: glyph, rect: null };
}
this.index[key] = rect;
this.ids[key] = [id];
var target = this.data;
var source = glyph.bitmap;
for (var y = 0; y < bufferedHeight; y++) {
var y1 = this.width * (rect.y + y + padding) + rect.x + padding;
var y2 = bufferedWidth * y;
for (var x = 0; x < bufferedWidth; x++) {
target[y1 + x] = source[y2 + x];
}
}
this.dirty = true;
return rect;
};
GlyphAtlas.prototype.bind = function(gl) {
this.gl = gl;
if (!this.texture) {
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, this.width, this.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null);
} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);
}
};
GlyphAtlas.prototype.updateTexture = function(gl) {
this.bind(gl);
if (this.dirty) {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.ALPHA, gl.UNSIGNED_BYTE, this.data);
// DEBUG
if (this.ctx) {
var data = this.ctx.getImageData(0, 0, this.width, this.height);
for (var i = 0, j = 0; i < this.data.length; i++, j += 4) {
data.data[j] = this.data[i];
data.data[j + 1] = this.data[i];
data.data[j + 2] = this.data[i];
data.data[j + 3] = 255;
}
this.ctx.putImageData(data, 0, 0);
this.ctx.strokeStyle = 'red';
for (var k = 0; k < this.bin.free.length; k++) {
var free = this.bin.free[k];
this.ctx.strokeRect(free.x, free.y, free.w, free.h);
}
}
// END DEBUG
this.dirty = false;
}
};
},{"./bin_pack":59}],67:[function(require,module,exports){
'use strict';
var normalizeURL = require('../util/mapbox').normalizeGlyphsURL;
var getArrayBuffer = require('../util/ajax').getArrayBuffer;
var Glyphs = require('../util/glyphs');
var Protobuf = require('pbf');
module.exports = GlyphSource;
/**
* A glyph source has a URL from which to load new glyphs and owns a GlyphAtlas
* that stores currently-loaded glyphs.
*
* @param {string} url glyph template url
* @param {Object} glyphAtlas glyph atlas object
* @private
*/
function GlyphSource(url, glyphAtlas) {
this.url = url && normalizeURL(url);
this.glyphAtlas = glyphAtlas;
this.stacks = [];
this.loading = {};
}
GlyphSource.prototype.getSimpleGlyphs = function(fontstack, glyphIDs, uid, callback) {
if (this.stacks[fontstack] === undefined) this.stacks[fontstack] = {};
var glyphs = {};
var stack = this.stacks[fontstack];
var glyphAtlas = this.glyphAtlas;
// the number of pixels the sdf bitmaps are padded by
var buffer = 3;
var missing = {};
var remaining = 0;
var range;
for (var i = 0; i < glyphIDs.length; i++) {
var glyphID = glyphIDs[i];
range = Math.floor(glyphID / 256);
if (stack[range]) {
var glyph = stack[range].glyphs[glyphID];
var rect = glyphAtlas.addGlyph(uid, fontstack, glyph, buffer);
if (glyph) glyphs[glyphID] = new SimpleGlyph(glyph, rect, buffer);
} else {
if (missing[range] === undefined) {
missing[range] = [];
remaining++;
}
missing[range].push(glyphID);
}
}
if (!remaining) callback(undefined, glyphs);
var onRangeLoaded = function(err, range, data) {
// TODO not be silent about errors
if (!err) {
var stack = this.stacks[fontstack][range] = data.stacks[0];
for (var i = 0; i < missing[range].length; i++) {
var glyphID = missing[range][i];
var glyph = stack.glyphs[glyphID];
var rect = glyphAtlas.addGlyph(uid, fontstack, glyph, buffer);
if (glyph) glyphs[glyphID] = new SimpleGlyph(glyph, rect, buffer);
}
}
remaining--;
if (!remaining) callback(undefined, glyphs);
}.bind(this);
for (var r in missing) {
this.loadRange(fontstack, r, onRangeLoaded);
}
};
// A simplified representation of the glyph containing only the properties needed for shaping.
function SimpleGlyph(glyph, rect, buffer) {
var padding = 1;
this.advance = glyph.advance;
this.left = glyph.left - buffer - padding;
this.top = glyph.top + buffer + padding;
this.rect = rect;
}
GlyphSource.prototype.loadRange = function(fontstack, range, callback) {
if (range * 256 > 65535) return callback('gyphs > 65535 not supported');
if (this.loading[fontstack] === undefined) this.loading[fontstack] = {};
var loading = this.loading[fontstack];
if (loading[range]) {
loading[range].push(callback);
} else {
loading[range] = [callback];
var rangeName = (range * 256) + '-' + (range * 256 + 255);
var url = glyphUrl(fontstack, rangeName, this.url);
getArrayBuffer(url, function(err, data) {
var glyphs = !err && new Glyphs(new Protobuf(new Uint8Array(data)));
for (var i = 0; i < loading[range].length; i++) {
loading[range][i](err, range, glyphs);
}
delete loading[range];
});
}
};
/**
* Use CNAME sharding to load a specific glyph range over a randomized
* but consistent subdomain.
* @param {string} fontstack comma-joined fonts
* @param {string} range comma-joined range
* @param {url} url templated url
* @param {string} [subdomains=abc] subdomains as a string where each letter is one.
* @returns {string} a url to load that section of glyphs
* @private
*/
function glyphUrl(fontstack, range, url, subdomains) {
subdomains = subdomains || 'abc';
return url
.replace('{s}', subdomains[fontstack.length % subdomains.length])
.replace('{fontstack}', fontstack)
.replace('{range}', range);
}
},{"../util/ajax":84,"../util/glyphs":91,"../util/mapbox":93,"pbf":111}],68:[function(require,module,exports){
'use strict';
module.exports = function (features, textFeatures, geometries) {
var leftIndex = {},
rightIndex = {},
mergedFeatures = [],
mergedGeom = [],
mergedTexts = [],
mergedIndex = 0,
k;
function add(k) {
mergedFeatures.push(features[k]);
mergedGeom.push(geometries[k]);
mergedTexts.push(textFeatures[k]);
mergedIndex++;
}
function mergeFromRight(leftKey, rightKey, geom) {
var i = rightIndex[leftKey];
delete rightIndex[leftKey];
rightIndex[rightKey] = i;
mergedGeom[i][0].pop();
mergedGeom[i][0] = mergedGeom[i][0].concat(geom[0]);
return i;
}
function mergeFromLeft(leftKey, rightKey, geom) {
var i = leftIndex[rightKey];
delete leftIndex[rightKey];
leftIndex[leftKey] = i;
mergedGeom[i][0].shift();
mergedGeom[i][0] = geom[0].concat(mergedGeom[i][0]);
return i;
}
function getKey(text, geom, onRight) {
var point = onRight ? geom[0][geom[0].length - 1] : geom[0][0];
return text + ':' + point.x + ':' + point.y;
}
for (k = 0; k < features.length; k++) {
var geom = geometries[k],
text = textFeatures[k];
if (!text) {
add(k);
continue;
}
var leftKey = getKey(text, geom),
rightKey = getKey(text, geom, true);
if ((leftKey in rightIndex) && (rightKey in leftIndex) && (rightIndex[leftKey] !== leftIndex[rightKey])) {
// found lines with the same text adjacent to both ends of the current line, merge all three
var j = mergeFromLeft(leftKey, rightKey, geom);
var i = mergeFromRight(leftKey, rightKey, mergedGeom[j]);
delete leftIndex[leftKey];
delete rightIndex[rightKey];
rightIndex[getKey(text, mergedGeom[i], true)] = i;
mergedGeom[j] = null;
} else if (leftKey in rightIndex) {
// found mergeable line adjacent to the start of the current line, merge
mergeFromRight(leftKey, rightKey, geom);
} else if (rightKey in leftIndex) {
// found mergeable line adjacent to the end of the current line, merge
mergeFromLeft(leftKey, rightKey, geom);
} else {
// no adjacent lines, add as a new item
add(k);
leftIndex[leftKey] = mergedIndex - 1;
rightIndex[rightKey] = mergedIndex - 1;
}
}
return {
features: mergedFeatures,
textFeatures: mergedTexts,
geometries: mergedGeom
};
};
},{}],69:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
var Anchor = require('../symbol/anchor');
module.exports = {
getIconQuads: getIconQuads,
getGlyphQuads: getGlyphQuads
};
var minScale = 0.5; // underscale by 1 zoom level
function SymbolQuad(anchor, tl, tr, bl, br, tex, angle, minScale, maxScale) {
this.anchor = anchor;
this.tl = tl;
this.tr = tr;
this.bl = bl;
this.br = br;
this.tex = tex;
this.angle = angle;
this.minScale = minScale;
this.maxScale = maxScale;
}
function getIconQuads(anchor, shapedIcon, boxScale, line, layout, alongLine) {
var rect = shapedIcon.image.rect;
var border = 1;
var left = shapedIcon.left - border;
var right = left + rect.w;
var top = shapedIcon.top - border;
var bottom = top + rect.h;
var tl = new Point(left, top);
var tr = new Point(right, top);
var br = new Point(right, bottom);
var bl = new Point(left, bottom);
var angle = layout['icon-rotate'] * Math.PI / 180;
if (alongLine) {
var prev = line[anchor.segment];
angle += Math.atan2(anchor.y - prev.y, anchor.x - prev.x);
}
if (angle) {
var sin = Math.sin(angle),
cos = Math.cos(angle),
matrix = [cos, -sin, sin, cos];
tl = tl.matMult(matrix);
tr = tr.matMult(matrix);
bl = bl.matMult(matrix);
br = br.matMult(matrix);
}
return [new SymbolQuad(anchor, tl, tr, bl, br, shapedIcon.image.rect, 0, minScale, Infinity)];
}
function getGlyphQuads(anchor, shaping, boxScale, line, layout, alongLine) {
var textRotate = layout['text-rotate'] * Math.PI / 180;
var keepUpright = layout['text-keep-upright'];
var positionedGlyphs = shaping.positionedGlyphs;
var quads = [];
for (var k = 0; k < positionedGlyphs.length; k++) {
var positionedGlyph = positionedGlyphs[k];
var glyph = positionedGlyph.glyph;
var rect = glyph.rect;
if (!rect) continue;
var centerX = (positionedGlyph.x + glyph.advance / 2) * boxScale;
var glyphInstances;
var labelMinScale = minScale;
if (alongLine) {
glyphInstances = [];
labelMinScale = getSegmentGlyphs(glyphInstances, anchor, centerX, line, anchor.segment, 1);
if (keepUpright) {
labelMinScale = Math.min(labelMinScale, getSegmentGlyphs(glyphInstances, anchor, centerX, line, anchor.segment, -1));
}
} else {
glyphInstances = [{
anchor: anchor,
offset: 0,
angle: 0,
maxScale: Infinity,
minScale: minScale
}];
}
var x1 = positionedGlyph.x + glyph.left,
y1 = positionedGlyph.y - glyph.top,
x2 = x1 + rect.w,
y2 = y1 + rect.h,
otl = new Point(x1, y1),
otr = new Point(x2, y1),
obl = new Point(x1, y2),
obr = new Point(x2, y2);
for (var i = 0; i < glyphInstances.length; i++) {
var instance = glyphInstances[i],
tl = otl,
tr = otr,
bl = obl,
br = obr,
angle = instance.angle + textRotate;
if (angle) {
var sin = Math.sin(angle),
cos = Math.cos(angle),
matrix = [cos, -sin, sin, cos];
tl = tl.matMult(matrix);
tr = tr.matMult(matrix);
bl = bl.matMult(matrix);
br = br.matMult(matrix);
}
// Prevent label from extending past the end of the line
var glyphMinScale = Math.max(instance.minScale, labelMinScale);
var glyphAngle = (anchor.angle + textRotate + instance.offset + 2 * Math.PI) % (2 * Math.PI);
quads.push(new SymbolQuad(instance.anchor, tl, tr, bl, br, rect, glyphAngle, glyphMinScale, instance.maxScale));
}
}
return quads;
}
function getSegmentGlyphs(glyphs, anchor, offset, line, segment, direction) {
var upsideDown = direction < 0;
if (offset < 0) direction *= -1;
if (direction > 0) segment++;
var newAnchor = anchor;
var end = line[segment];
var prevScale = Infinity;
offset = Math.abs(offset);
var placementScale = minScale;
while (true) {
var distance = newAnchor.dist(end);
var scale = offset / distance;
// Get the angle of the line segment
var angle = Math.atan2(end.y - newAnchor.y, end.x - newAnchor.x);
if (direction < 0) angle += Math.PI;
if (upsideDown) angle += Math.PI;
glyphs.push({
anchor: new Anchor(newAnchor.x, newAnchor.y, anchor.angle),
offset: upsideDown ? Math.PI : 0,
minScale: scale,
maxScale: prevScale,
angle: (angle + 2 * Math.PI) % (2 * Math.PI)
});
if (scale <= placementScale) break;
newAnchor = end;
// skip duplicate nodes
while (newAnchor.equals(end)) {
segment += direction;
end = line[segment];
if (!end) {
return scale;
}
}
var unit = end.sub(newAnchor)._unit();
newAnchor = newAnchor.sub(unit._mult(distance));
prevScale = scale;
}
return placementScale;
}
},{"../symbol/anchor":58,"point-geometry":113}],70:[function(require,module,exports){
'use strict';
var resolveTokens = require('../util/token');
module.exports = resolveIcons;
// For an array of features determine what icons need to be loaded.
function resolveIcons(features, layoutProperties) {
var icons = [];
for (var i = 0, fl = features.length; i < fl; i++) {
var text = resolveTokens(features[i].properties, layoutProperties['icon-image']);
if (!text) continue;
if (icons.indexOf(text) < 0) {
icons.push(text);
}
}
return icons;
}
},{"../util/token":95}],71:[function(require,module,exports){
'use strict';
var resolveTokens = require('../util/token');
module.exports = resolveText;
/**
* For an array of features determine what glyph ranges need to be loaded
* and apply any text preprocessing. The remaining users of text should
* use the `textFeatures` key returned by this function rather than accessing
* feature text directly.
* @private
*/
function resolveText(features, layoutProperties, glyphs) {
var textFeatures = [];
var codepoints = [];
for (var i = 0, fl = features.length; i < fl; i++) {
var text = resolveTokens(features[i].properties, layoutProperties['text-field']);
if (!text) {
textFeatures[i] = null;
continue;
}
text = text.toString();
var transform = layoutProperties['text-transform'];
if (transform === 'uppercase') {
text = text.toLocaleUpperCase();
} else if (transform === 'lowercase') {
text = text.toLocaleLowerCase();
}
for (var j = 0, jl = text.length; j < jl; j++) {
codepoints.push(text.charCodeAt(j));
}
// Track indexes of features with text.
textFeatures[i] = text;
}
// get a list of unique codepoints we are missing
codepoints = uniq(codepoints, glyphs);
return {
textFeatures: textFeatures,
codepoints: codepoints
};
}
function uniq(ids, alreadyHave) {
var u = [];
var last;
ids.sort(sortNumbers);
for (var i = 0; i < ids.length; i++) {
if (ids[i] !== last) {
last = ids[i];
if (!alreadyHave[last]) u.push(ids[i]);
}
}
return u;
}
function sortNumbers(a, b) {
return a - b;
}
},{"../util/token":95}],72:[function(require,module,exports){
'use strict';
module.exports = {
shapeText: shapeText,
shapeIcon: shapeIcon
};
// The position of a glyph relative to the text's anchor point.
function PositionedGlyph(codePoint, x, y, glyph) {
this.codePoint = codePoint;
this.x = x;
this.y = y;
this.glyph = glyph;
}
// A collection of positioned glyphs and some metadata
function Shaping(positionedGlyphs, top, bottom, left, right) {
this.positionedGlyphs = positionedGlyphs;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
}
function shapeText(text, glyphs, maxWidth, lineHeight, horizontalAlign, verticalAlign, justify, spacing, translate) {
var positionedGlyphs = [];
var shaping = new Shaping(positionedGlyphs, translate[1], translate[1], translate[0], translate[0]);
// the y offset *should* be part of the font metadata
var yOffset = -17;
var x = translate[0];
var y = translate[1] + yOffset;
for (var i = 0; i < text.length; i++) {
var codePoint = text.charCodeAt(i);
var glyph = glyphs[codePoint];
if (!glyph) continue;
positionedGlyphs.push(new PositionedGlyph(codePoint, x, y, glyph));
x += glyph.advance + spacing;
}
if (!positionedGlyphs.length) return false;
linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify);
return shaping;
}
var breakable = { 32: true }; // Currently only breaks at regular spaces
function linewrap(shaping, glyphs, lineHeight, maxWidth, horizontalAlign, verticalAlign, justify) {
var lastSafeBreak = null;
var lengthBeforeCurrentLine = 0;
var lineStartIndex = 0;
var line = 0;
var maxLineLength = 0;
var positionedGlyphs = shaping.positionedGlyphs;
if (maxWidth) {
for (var i = 0; i < positionedGlyphs.length; i++) {
var positionedGlyph = positionedGlyphs[i];
positionedGlyph.x -= lengthBeforeCurrentLine;
positionedGlyph.y += lineHeight * line;
if (positionedGlyph.x > maxWidth && lastSafeBreak !== null) {
var lineLength = positionedGlyphs[lastSafeBreak + 1].x;
maxLineLength = Math.max(lineLength, maxLineLength);
for (var k = lastSafeBreak + 1; k <= i; k++) {
positionedGlyphs[k].y += lineHeight;
positionedGlyphs[k].x -= lineLength;
}
if (justify) {
justifyLine(positionedGlyphs, glyphs, lineStartIndex, lastSafeBreak - 1, justify);
}
lineStartIndex = lastSafeBreak + 1;
lastSafeBreak = null;
lengthBeforeCurrentLine += lineLength;
line++;
}
if (breakable[positionedGlyph.codePoint]) {
lastSafeBreak = i;
}
}
}
var lastPositionedGlyph = positionedGlyphs[positionedGlyphs.length - 1];
var lastLineLength = lastPositionedGlyph.x + glyphs[lastPositionedGlyph.codePoint].advance;
maxLineLength = Math.max(maxLineLength, lastLineLength);
var height = (line + 1) * lineHeight;
justifyLine(positionedGlyphs, glyphs, lineStartIndex, positionedGlyphs.length - 1, justify);
align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line);
// Calculate the bounding box
shaping.top += -verticalAlign * height;
shaping.bottom = shaping.top + height;
shaping.left += -horizontalAlign * maxLineLength;
shaping.right = shaping.left + maxLineLength;
}
function justifyLine(positionedGlyphs, glyphs, start, end, justify) {
var lastAdvance = glyphs[positionedGlyphs[end].codePoint].advance;
var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
for (var j = start; j <= end; j++) {
positionedGlyphs[j].x -= lineIndent;
}
}
function align(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line) {
var shiftX = (justify - horizontalAlign) * maxLineLength;
var shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight;
for (var j = 0; j < positionedGlyphs.length; j++) {
positionedGlyphs[j].x += shiftX;
positionedGlyphs[j].y += shiftY;
}
}
function shapeIcon(image, layout) {
if (!image || !image.rect) return null;
var dx = layout['icon-offset'][0];
var dy = layout['icon-offset'][1];
var x1 = dx - image.width / 2;
var x2 = x1 + image.width;
var y1 = dy - image.height / 2;
var y2 = y1 + image.height;
return new PositionedIcon(image, y1, y2, x1, x2);
}
function PositionedIcon(image, top, bottom, left, right) {
this.image = image;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
}
},{}],73:[function(require,module,exports){
'use strict';
var BinPack = require('./bin_pack');
module.exports = SpriteAtlas;
function SpriteAtlas(width, height) {
this.width = width;
this.height = height;
this.bin = new BinPack(width, height);
this.images = {};
this.data = false;
this.texture = 0; // WebGL ID
this.filter = 0; // WebGL ID
this.pixelRatio = 1;
this.dirty = true;
}
SpriteAtlas.prototype = {
get debug() {
return 'canvas' in this;
},
set debug(value) {
if (value && !this.canvas) {
this.canvas = document.createElement('canvas');
this.canvas.width = this.width * this.pixelRatio;
this.canvas.height = this.height * this.pixelRatio;
this.canvas.style.width = this.width + 'px';
this.canvas.style.width = this.width + 'px';
document.body.appendChild(this.canvas);
this.ctx = this.canvas.getContext('2d');
} else if (!value && this.canvas) {
this.canvas.parentNode.removeChild(this.canvas);
delete this.ctx;
delete this.canvas;
}
}
};
SpriteAtlas.prototype.resize = function(newRatio) {
if (this.pixelRatio === newRatio) return false;
var oldRatio = this.pixelRatio;
this.pixelRatio = newRatio;
if (this.canvas) {
this.canvas.width = this.width * this.pixelRatio;
this.canvas.height = this.height * this.pixelRatio;
}
if (this.data) {
var oldData = this.data;
this.data = false;
this.allocate();
this.texture = false;
var oldWidth = this.width * oldRatio;
var oldHeight = this.height * oldRatio;
var newWidth = this.width * newRatio;
var newHeight = this.height * newRatio;
// Basic image scaling. TODO: Replace this with better image scaling.
var newImage = this.data;
var oldImage = oldData;
for (var y = 0; y < newHeight; y++) {
var oldYOffset = Math.floor((y * oldHeight) / newHeight) * oldWidth;
var newYOffset = y * newWidth;
for (var x = 0; x < newWidth; x++) {
var oldX = Math.floor((x * oldWidth) / newWidth);
newImage[newYOffset + x] = oldImage[oldYOffset + oldX];
}
}
oldData = null;
this.dirty = true;
}
return this.dirty;
};
function copyBitmap(src, srcStride, srcX, srcY, dst, dstStride, dstX, dstY, width, height, wrap) {
var srcI = srcY * srcStride + srcX;
var dstI = dstY * dstStride + dstX;
var x, y;
if (wrap) {
// add 1 pixel wrapped padding on each side of the image
dstI -= dstStride;
for (y = -1; y <= height; y++, srcI = ((y + height) % height + srcY) * srcStride + srcX, dstI += dstStride) {
for (x = -1; x <= width; x++) {
dst[dstI + x] = src[srcI + ((x + width) % width)];
}
}
} else {
for (y = 0; y < height; y++, srcI += srcStride, dstI += dstStride) {
for (x = 0; x < width; x++) {
dst[dstI + x] = src[srcI + x];
}
}
}
}
SpriteAtlas.prototype.allocateImage = function(pixelWidth, pixelHeight) {
// Increase to next number divisible by 4, but at least 1.
// This is so we can scale down the texture coordinates and pack them
// into 2 bytes rather than 4 bytes.
// Pad icons to prevent them from polluting neighbours during linear interpolation
var padding = 2;
var packWidth = pixelWidth + padding + (4 - (pixelWidth + padding) % 4);
var packHeight = pixelHeight + padding + (4 - (pixelHeight + padding) % 4);// + 4;
// We have to allocate a new area in the bin, and store an empty image in it.
// Add a 1px border around every image.
var rect = this.bin.allocate(packWidth, packHeight);
if (rect.w === 0) {
return rect;
}
rect.originalWidth = pixelWidth;
rect.originalHeight = pixelHeight;
return rect;
};
SpriteAtlas.prototype.getImage = function(name, wrap) {
if (this.images[name]) {
return this.images[name];
}
if (!this.sprite) {
return null;
}
var pos = this.sprite.getSpritePosition(name);
if (!pos.width || !pos.height) {
return null;
}
var width = pos.width / pos.pixelRatio;
var height = pos.height / pos.pixelRatio;
var rect = this.allocateImage(width, height);
if (rect.w === 0) {
return rect;
}
var image = new AtlasImage(rect, width, height, pos.sdf);
this.images[name] = image;
this.copy(rect, pos, wrap);
return image;
};
SpriteAtlas.prototype.getPosition = function(name, repeating) {
var image = this.getImage(name, repeating);
var rect = image && image.rect;
if (!rect) {
return null;
}
// When the image is repeating, get the correct position of the image, rather than the
// one rounded up to 4 pixels.
var width = repeating ? image.width : rect.w;
var height = repeating ? image.height : rect.h;
var padding = 1;
return {
size: [width, height],
tl: [(rect.x + padding) / this.width, (rect.y + padding) / this.height],
br: [(rect.x + padding + width) / this.width, (rect.y + padding + height) / this.height]
};
};
SpriteAtlas.prototype.allocate = function() {
if (!this.data) {
var w = Math.floor(this.width * this.pixelRatio);
var h = Math.floor(this.height * this.pixelRatio);
this.data = new Uint32Array(w * h);
for (var i = 0; i < this.data.length; i++) {
this.data[i] = 0;
}
}
};
SpriteAtlas.prototype.copy = function(dst, src, wrap) {
// if (!sprite->raster) return;
if (!this.sprite.img.data) return;
var srcImg = new Uint32Array(this.sprite.img.data.buffer);
this.allocate();
var dstImg = this.data;
var padding = 1;
copyBitmap(
/* source buffer */ srcImg,
/* source stride */ this.sprite.img.width,
/* source x */ src.x,
/* source y */ src.y,
/* dest buffer */ dstImg,
/* dest stride */ this.width * this.pixelRatio,
/* dest x */ (dst.x + padding) * this.pixelRatio,
/* dest y */ (dst.y + padding) * this.pixelRatio,
/* icon dimension */ src.width,
/* icon dimension */ src.height,
/* wrap */ wrap
);
this.dirty = true;
};
SpriteAtlas.prototype.setSprite = function(sprite) {
this.sprite = sprite;
};
SpriteAtlas.prototype.addIcons = function(icons, callback) {
for (var i = 0; i < icons.length; i++) {
this.getImage(icons[i]);
}
callback(null, this.images);
};
SpriteAtlas.prototype.bind = function(gl, linear) {
var first = false;
if (!this.texture) {
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
first = true;
} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);
}
var filterVal = linear ? gl.LINEAR : gl.NEAREST;
if (filterVal !== this.filter) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterVal);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterVal);
this.filter = filterVal;
}
if (this.dirty) {
this.allocate();
if (first) {
gl.texImage2D(
gl.TEXTURE_2D, // enum target
0, // ind level
gl.RGBA, // ind internalformat
this.width * this.pixelRatio, // GLsizei width
this.height * this.pixelRatio, // GLsizei height
0, // ind border
gl.RGBA, // enum format
gl.UNSIGNED_BYTE, // enum type
new Uint8Array(this.data.buffer) // Object data
);
} else {
gl.texSubImage2D(
gl.TEXTURE_2D, // enum target
0, // int level
0, // int xoffset
0, // int yoffset
this.width * this.pixelRatio, // long width
this.height * this.pixelRatio, // long height
gl.RGBA, // enum format
gl.UNSIGNED_BYTE, // enum type
new Uint8Array(this.data.buffer) // Object pixels
);
}
this.dirty = false;
// DEBUG
if (this.ctx) {
var data = this.ctx.getImageData(0, 0, this.width * this.pixelRatio, this.height * this.pixelRatio);
data.data.set(new Uint8ClampedArray(this.data.buffer));
this.ctx.putImageData(data, 0, 0);
this.ctx.strokeStyle = 'red';
for (var k = 0; k < this.bin.free.length; k++) {
var free = this.bin.free[k];
this.ctx.strokeRect(free.x * this.pixelRatio, free.y * this.pixelRatio, free.w * this.pixelRatio, free.h * this.pixelRatio);
}
}
// END DEBUG
}
};
function AtlasImage(rect, width, height, sdf) {
this.rect = rect;
this.width = width;
this.height = height;
this.sdf = sdf;
}
},{"./bin_pack":59}],74:[function(require,module,exports){
'use strict';
var util = require('../util/util');
var interpolate = require('../util/interpolate');
var browser = require('../util/browser');
var LatLng = require('../geo/lat_lng');
var LatLngBounds = require('../geo/lat_lng_bounds');
var Point = require('point-geometry');
/**
* @typedef {Object} CameraOptions
* @property {Array} [center] Latitude and longitude (passed as `[lat, lng]`)
* @property {number} [zoom] Map zoom level
* @property {number} [bearing] Map rotation bearing in degrees counter-clockwise from north
* @property {number} [pitch] The angle at which the camera is looking at the ground
*/
/**
* @typedef {Object} [AnimationOptions]
* @property {number} [duration=500] Number in milliseconds
* @property {Function} [easing]
* @property {Array} [offset=[0,0]] point, origin of movement relative to map center
* @property {boolean} [animate=true] When set to false, no animation happens
*/
var Camera = module.exports = function() {};
util.extend(Camera.prototype, /** @lends Map.prototype */{
/**
* Get the current view geographical point.
* @returns {LatLng}
*/
getCenter: function() { return this.transform.center; },
/**
* Sets a map location. Equivalent to `jumpTo({center: center})`.
*
* @param {Array} center Latitude and longitude (passed as `[lat, lng]`)
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* map.setCenter([-74, 38]);
*/
setCenter: function(center) {
this.jumpTo({center: center});
},
/**
* Pan by a certain number of pixels
*
* @param {Array} offset [x, y]
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
panBy: function(offset, options) {
this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));
return this;
},
/**
* Pan to a certain location with easing
*
* @param {Object} latlng a `LatLng` object
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
panTo: function(latlng, options) {
this.stop();
latlng = LatLng.convert(latlng);
options = util.extend({
duration: 500,
easing: util.ease,
offset: [0, 0]
}, options);
var tr = this.transform,
offset = Point.convert(options.offset).rotate(-tr.angle),
from = tr.point,
to = tr.project(latlng).sub(offset);
if (!options.noMoveStart) {
this.fire('movestart');
}
this._ease(function(k) {
tr.center = tr.unproject(from.add(to.sub(from).mult(k)));
this.fire('move');
}, function() {
this.fire('moveend');
}, options);
return this;
},
/**
* Get the current zoom
* @returns {number}
*/
getZoom: function() { return this.transform.zoom; },
/**
* Sets a map zoom. Equivalent to `jumpTo({zoom: zoom})`.
*
* @param {number} zoom Map zoom level
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* // zoom the map to 5
* map.setZoom(5);
*/
setZoom: function(zoom) {
this.jumpTo({zoom: zoom});
},
/**
* Zooms to a certain zoom level with easing.
*
* @param {Number} zoom
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomTo: function(zoom, options) {
this.stop();
options = util.extend({
duration: 500
}, options);
options.easing = this._updateEasing(options.duration, zoom, options.easing);
var tr = this.transform,
around = tr.center,
startZoom = tr.zoom;
if (options.around) {
around = LatLng.convert(options.around);
} else if (options.offset) {
around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));
}
if (options.animate === false) options.duration = 0;
if (!this.zooming) {
this.zooming = true;
this.fire('movestart');
}
this._ease(function(k) {
tr.setZoomAround(interpolate(startZoom, zoom, k), around);
this.fire('move').fire('zoom');
}, function() {
this.ease = null;
if (options.duration >= 200) {
this.zooming = false;
this.fire('moveend');
}
}, options);
if (options.duration < 200) {
clearTimeout(this._onZoomEnd);
this._onZoomEnd = setTimeout(function() {
this.zooming = false;
this.fire('moveend');
}.bind(this), 200);
}
return this;
},
/**
* Zoom in by 1 level
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomIn: function(options) {
this.zoomTo(this.getZoom() + 1, options);
},
/**
* Zoom out by 1 level
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
zoomOut: function(options) {
this.zoomTo(this.getZoom() - 1, options);
},
/**
* Get the current bearing in degrees
* @returns {number}
*/
getBearing: function() { return this.transform.bearing; },
/**
* Sets a map rotation. Equivalent to `jumpTo({bearing: bearing})`.
*
* @param {number} bearing Map rotation bearing in degrees counter-clockwise from north
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* // rotate the map to 90 degrees
* map.setBearing(90);
*/
setBearing: function(bearing) {
this.jumpTo({bearing: bearing});
},
/**
* Rotate bearing by a certain number of degrees with easing
*
* @param {Number} bearing
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
rotateTo: function(bearing, options) {
this.stop();
options = util.extend({
duration: 500,
easing: util.ease
}, options);
var tr = this.transform,
start = this.getBearing(),
around = tr.center;
if (options.around) {
around = LatLng.convert(options.around);
} else if (options.offset) {
around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));
}
bearing = this._normalizeBearing(bearing, start);
this.rotating = true;
this.fire('movestart');
this._ease(function(k) {
tr.setBearingAround(interpolate(start, bearing, k), around);
this.fire('move').fire('rotate');
}, function() {
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
/**
* Sets map bearing to 0 (north) with easing
*
* @param {AnimationOptions}
* @fires movestart
* @fires moveend
* @returns {this}
*/
resetNorth: function(options) {
return this.rotateTo(0, util.extend({duration: 1000}, options));
},
/**
* Get the current angle in degrees
* @returns {number}
*/
getPitch: function() { return this.transform.pitch; },
/**
* Sets a map angle. Equivalent to `jumpTo({pitch: pitch})`.
*
* @param {number} pitch The angle at which the camera is looking at the ground
* @fires movestart
* @fires moveend
* @returns {Map} `this`
*/
setPitch: function(pitch) {
this.jumpTo({pitch: pitch});
},
/**
* Zoom to contain certain geographical bounds
*
* @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]
* @param {Object} options
* @param {Number} [options.speed=1.2] How fast animation occurs
* @param {Number} [options.curve=1.42] How much zooming out occurs during animation
* @param {Function} options.easing
* @param {Number} options.padding how much padding there is around the given bounds on each side in pixels
* @param {Number} options.maxZoom
* @fires movestart
* @fires moveend
* @returns {this}
*/
fitBounds: function(bounds, options) {
options = util.extend({
padding: 0,
offset: [0, 0],
maxZoom: Infinity
}, options);
bounds = LatLngBounds.convert(bounds);
var offset = Point.convert(options.offset),
tr = this.transform,
nw = tr.project(bounds.getNorthWest()),
se = tr.project(bounds.getSouthEast()),
size = se.sub(nw),
scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,
scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y;
options.center = tr.unproject(nw.add(se).div(2));
options.zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);
options.bearing = 0;
return options.linear ?
this.easeTo(options) :
this.flyTo(options);
},
/**
* Change any combination of center, zoom, bearing, and pitch, without
* a transition. The map will retain the current values for any options
* not included in `options`.
*
* @param {CameraOptions} options map view options
* @fires movestart
* @fires moveend
* @returns {Map} `this`
*/
jumpTo: function(options) {
this.stop();
var tr = this.transform,
zoomChanged = false,
bearingChanged = false,
pitchChanged = false;
if ('center' in options) {
tr.center = LatLng.convert(options.center);
}
if ('zoom' in options && tr.zoom !== +options.zoom) {
zoomChanged = true;
tr.zoom = +options.zoom;
}
if ('bearing' in options && tr.bearing !== +options.bearing) {
bearingChanged = true;
tr.bearing = +options.bearing;
}
if ('pitch' in options && tr.pitch !== +options.pitch) {
pitchChanged = true;
tr.pitch = +options.pitch;
}
this.fire('movestart')
.fire('move');
if (zoomChanged) {
this.fire('zoom');
}
if (bearingChanged) {
this.fire('rotate');
}
if (pitchChanged) {
this.fire('pitch');
}
return this.fire('moveend');
},
/**
* Easing animation to a specified location/zoom/bearing
*
* @param {CameraOptions+AnimationOptions} options map view and animation options
* @fires movestart
* @fires moveend
* @returns {this}
*/
easeTo: function(options) {
this.stop();
options = util.extend({
offset: [0, 0],
duration: 500,
easing: util.ease
}, options);
var tr = this.transform,
offset = Point.convert(options.offset).rotate(-tr.angle),
from = tr.point,
startZoom = this.getZoom(),
startBearing = this.getBearing(),
startPitch = this.getPitch();
var zoom = 'zoom' in options ? +options.zoom : startZoom;
var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing;
var pitch = 'pitch' in options ? +options.pitch : startPitch;
var scale = tr.zoomScale(zoom - startZoom),
to = 'center' in options ? tr.project(LatLng.convert(options.center)).sub(offset.div(scale)) : from,
around;
if (zoom !== startZoom) {
around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));
this.zooming = true;
}
if (startBearing !== bearing) {
this.rotating = true;
}
this.fire('movestart');
this._ease(function (k) {
if (zoom !== startZoom) {
tr.setZoomAround(interpolate(startZoom, zoom, k), around);
} else {
tr.center = tr.unproject(from.add(to.sub(from).mult(k)));
}
if (bearing !== startBearing) {
tr.bearing = interpolate(startBearing, bearing, k);
}
if (pitch !== startPitch) {
tr.pitch = interpolate(startPitch, pitch, k);
}
this.fire('move');
if (this.zooming) {
this.fire('zoom');
}
if (this.rotating) {
this.fire('rotate');
}
}, function() {
this.zooming = false;
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
/**
* Flying animation to a specified location/zoom/bearing with automatic curve
*
* @param {CameraOptions} options map view options
* @param {Number} [options.speed=1.2] How fast animation occurs
* @param {Number} [options.curve=1.42] How much zooming out occurs during animation
* @param {Function} [options.easing]
* @fires movestart
* @fires moveend
* @returns {this}
* @example
* // fly with default options to null island
* map.flyTo({center: [0, 0], zoom: 9});
* // using flyTo options
* map.flyTo({
* center: [0, 0],
* zoom: 9,
* speed: 0.2,
* curve: 1,
* easing: function(t) {
* return t;
* }
* });
*/
flyTo: function(options) {
this.stop();
options = util.extend({
offset: [0, 0],
speed: 1.2,
curve: 1.42,
easing: util.ease
}, options);
var tr = this.transform,
offset = Point.convert(options.offset),
startZoom = this.getZoom(),
startBearing = this.getBearing();
var center = 'center' in options ? LatLng.convert(options.center) : this.getCenter();
var zoom = 'zoom' in options ? +options.zoom : startZoom;
var bearing = 'bearing' in options ? this._normalizeBearing(options.bearing, startBearing) : startBearing;
var scale = tr.zoomScale(zoom - startZoom),
from = tr.point,
to = tr.project(center).sub(offset.div(scale));
var startWorldSize = tr.worldSize,
rho = options.curve,
V = options.speed,
w0 = Math.max(tr.width, tr.height),
w1 = w0 / scale,
u1 = to.sub(from).mag(),
rho2 = rho * rho;
function r(i) {
var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
return Math.log(Math.sqrt(b * b + 1) - b);
}
function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
function tanh(n) { return sinh(n) / cosh(n); }
var r0 = r(0),
w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },
u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },
S = (r(1) - r0) / rho;
if (Math.abs(u1) < 0.000001) {
if (Math.abs(w0 - w1) < 0.000001) return this;
var k = w1 < w0 ? -1 : 1;
S = Math.abs(Math.log(w1 / w0)) / rho;
u = function() { return 0; };
w = function(s) { return Math.exp(k * rho * s); };
}
options.duration = 1000 * S / V;
this.zooming = true;
if (startBearing !== bearing) this.rotating = true;
this.fire('movestart');
this._ease(function (k) {
var s = k * S,
us = u(s);
tr.zoom = startZoom + tr.scaleZoom(1 / w(s));
tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);
if (bearing !== startBearing) {
tr.bearing = interpolate(startBearing, bearing, k);
}
this.fire('move').fire('zoom');
if (bearing !== startBearing) {
this.fire('rotate');
}
}, function() {
this.zooming = false;
this.rotating = false;
this.fire('moveend');
}, options);
return this;
},
isEasing: function() {
return !!this._abortFn;
},
/**
* Stop current animation
*
* @returns {this}
*/
stop: function() {
if (this._abortFn) {
this._abortFn.call(this);
delete this._abortFn;
this._finishFn.call(this);
delete this._finishFn;
}
return this;
},
_ease: function(frame, finish, options) {
this._finishFn = finish;
this._abortFn = browser.timed(function (t) {
frame.call(this, options.easing(t));
if (t === 1) {
delete this._abortFn;
this._finishFn.call(this);
delete this._finishFn;
}
}, options.animate === false ? 0 : options.duration, this);
},
// convert bearing so that it's numerically close to the current one so that it interpolates properly
_normalizeBearing: function(bearing, currentBearing) {
bearing = util.wrap(bearing, -180, 180);
var diff = Math.abs(bearing - currentBearing);
if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;
if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;
return bearing;
},
_updateEasing: function(duration, zoom, bezier) {
var easing;
if (this.ease) {
var ease = this.ease,
t = (Date.now() - ease.start) / ease.duration,
speed = ease.easing(t + 0.01) - ease.easing(t),
// Quick hack to make new bezier that is continuous with last
x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,
y = Math.sqrt(0.27 * 0.27 - x * x);
easing = util.bezier(x, y, 0.25, 1);
} else {
easing = bezier ? util.bezier.apply(util, bezier) : util.ease;
}
// store information on current easing
this.ease = {
start: (new Date()).getTime(),
to: Math.pow(2, zoom),
duration: duration,
easing: easing
};
return easing;
}
});
},{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../util/browser":85,"../util/interpolate":92,"../util/util":96,"point-geometry":113}],75:[function(require,module,exports){
'use strict';
var Control = require('./control');
var DOM = require('../../util/dom');
var util = require('../../util/util');
module.exports = Attribution;
/**
* Creates an attribution control
* @class Attribution
* @example
* map.addControl(new mapboxgl.Attribution());
*/
function Attribution() {}
Attribution.prototype = util.inherit(Control, {
options: {
position: 'bottom-right'
},
onAdd: function(map) {
var className = 'mapboxgl-ctrl-attrib',
container = this._container = DOM.create('div', className, map.getContainer());
this._update();
map.on('source.load', this._update.bind(this));
map.on('source.change', this._update.bind(this));
map.on('source.remove', this._update.bind(this));
map.on('moveend', this._updateEditLink.bind(this));
return container;
},
_update: function() {
var attributions = [];
if (this._map.style) {
for (var id in this._map.style.sources) {
var source = this._map.style.sources[id];
if (source.attribution && attributions.indexOf(source.attribution) < 0) {
attributions.push(source.attribution);
}
}
}
this._container.innerHTML = attributions.join(' | ');
this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0];
this._updateEditLink();
},
_updateEditLink: function() {
if (this._editLink) {
var center = this._map.getCenter();
this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' +
center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1);
}
}
});
},{"../../util/dom":88,"../../util/util":96,"./control":76}],76:[function(require,module,exports){
'use strict';
module.exports = Control;
/**
* A base class for map-related interface elements.
*
* @class Control
*/
function Control() {}
Control.prototype = {
/**
* Add this control to the map, returning the control itself
* for chaining. This will insert the control's DOM element into
* the map's DOM element if the control has a `position` specified.
*
* @param {Map} map
* @returns {Control} this
*/
addTo: function(map) {
this._map = map;
var container = this._container = this.onAdd(map);
if (this.options && this.options.position) {
var pos = this.options.position;
var corner = map._controlCorners[pos];
container.className += ' mapboxgl-ctrl';
if (pos.indexOf('bottom') !== -1) {
corner.insertBefore(container, corner.firstChild);
} else {
corner.appendChild(container);
}
}
return this;
},
/**
* Remove this control from the map it has been added to.
*
* @returns {Control} this
*/
remove: function() {
this._container.parentNode.removeChild(this._container);
if (this.onRemove) this.onRemove(this._map);
this._map = null;
return this;
}
};
},{}],77:[function(require,module,exports){
'use strict';
var Control = require('./control');
var DOM = require('../../util/dom');
var util = require('../../util/util');
module.exports = Navigation;
/**
* Creates a navigation control with zoom buttons and a compass
* @class Navigation
* @param {Object} [options]
* @param {String} [options.position=top-right] A string indicating the control's position on the map. Options are `top-right`, `top-left`, `bottom-right`, `bottom-left`
* @example
* map.addControl(new mapboxgl.Navigation({position: 'top-left'})); // position is optional
*/
function Navigation(options) {
util.setOptions(this, options);
}
Navigation.prototype = util.inherit(Control, {
options: {
position: 'top-right'
},
onAdd: function(map) {
var className = 'mapboxgl-ctrl';
var container = this._container = DOM.create('div', className + '-group', map.getContainer());
this._zoomInButton = this._createButton(className + '-icon ' + className + '-zoom-in', map.zoomIn.bind(map));
this._zoomOutButton = this._createButton(className + '-icon ' + className + '-zoom-out', map.zoomOut.bind(map));
this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map));
var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass);
compassCanvas.style.cssText = 'width:30px; height:30px;';
compassCanvas.width = 26 * 2;
compassCanvas.height = 26 * 2;
this._compass.addEventListener('mousedown', this._onCompassDown.bind(this));
this._onCompassMove = this._onCompassMove.bind(this);
this._onCompassUp = this._onCompassUp.bind(this);
this._compassCtx = compassCanvas.getContext('2d');
map.on('rotate', this._drawNorth.bind(this));
this._drawNorth();
return container;
},
_onCompassDown: function(e) {
DOM.disableDrag();
document.addEventListener('mousemove', this._onCompassMove);
document.addEventListener('mouseup', this._onCompassUp);
this._prevX = e.screenX;
e.stopPropagation();
},
_onCompassMove: function(e) {
var x = e.screenX,
d = x < 2 ? -5 : // left edge of the screen, continue rotating
x > window.screen.width - 2 ? 5 : // right edge
(x - this._prevX) / 4;
this._map.setBearing(this._map.getBearing() - d);
this._prevX = e.screenX;
this._moved = true;
e.preventDefault();
},
_onCompassUp: function() {
document.removeEventListener('mousemove', this._onCompassMove);
document.removeEventListener('mouseup', this._onCompassUp);
DOM.enableDrag();
if (this._moved) {
this._moved = false;
DOM.suppressClick();
}
},
_createButton: function(className, fn) {
var a = DOM.create('button', className, this._container);
a.addEventListener('click', function() { fn(); });
return a;
},
_drawNorth: function() {
var rad = 20,
width = 8,
center = 26,
angle = this._map.transform.angle + (Math.PI / 2),
ctx = this._compassCtx;
this._compassCanvas.width = this._compassCanvas.width;
ctx.translate(center, center);
ctx.rotate(angle);
ctx.beginPath();
ctx.fillStyle = '#000';
ctx.lineTo(0, -width);
ctx.lineTo(-rad, 0);
ctx.lineTo(0, width);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = '#bbb';
ctx.moveTo(0, 0);
ctx.lineTo(0, width);
ctx.lineTo(rad, 0);
ctx.lineTo(0, -width);
ctx.fill();
ctx.beginPath();
ctx.strokeStyle = '#fff';
ctx.lineWidth = 4;
ctx.moveTo(0, -width);
ctx.lineTo(0, width);
ctx.stroke();
}
});
},{"../../util/dom":88,"../../util/util":96,"./control":76}],78:[function(require,module,exports){
'use strict';
var Interaction = require('./interaction');
var Point = require('point-geometry');
var util = require('../util/util');
var DOM = require('../util/dom');
var LatLngBounds = require('../geo/lat_lng_bounds');
module.exports = Handlers;
function Handlers(map) {
var rotateEnd;
var box;
var inertiaLinearity = 0.2,
inertiaEasing = util.bezier(0, 0, inertiaLinearity, 1);
function boxzoomFinish() {
if (box) {
box.parentNode.removeChild(box);
map.getContainer().classList.remove('mapboxgl-crosshair');
box = false;
DOM.enableDrag();
}
}
this.interaction = new Interaction(map.getCanvas())
.on('click', function(e) {
e.latLng = map.unproject(e.point);
map.fire('click', e);
})
.on('dblclick', function(e) {
e.latLng = map.unproject(e.point);
map.fire('dblclick', e);
})
.on('mousemove', function(e) {
e.latLng = map.unproject(e.point);
map.fire('mousemove', e);
})
.on('down', function() {
map.fire('movestart');
})
.on('resize', function() {
map.stop();
map.resize();
map.update();
})
.on('keydown', function(e) {
if (e.altKey || e.ctrlKey || e.metaKey) return;
var pan = 80;
var rotate = 2;
function zoomBy(z) {
map.zoomTo(Math.round(map.getZoom()) + (e.shiftKey ? 2 : 1) * z);
}
function panBy(v) {
map.panBy(v);
}
function rotateBy(v) {
map.setBearing(map.getBearing() + v);
}
switch (e.keyCode) {
case 61:
case 107:
case 171:
case 187:
zoomBy(1);
break;
case 189:
case 109:
case 173:
zoomBy(-1);
break;
case 37:
if (e.shiftKey) {
rotateBy(-rotate);
} else {
panBy([-pan, 0]);
}
break;
case 39:
if (e.shiftKey) {
rotateBy(rotate);
} else {
panBy([pan, 0]);
}
break;
case 38:
panBy([0, -pan]);
break;
case 40:
panBy([0, pan]);
break;
default:
return;
}
})
.on('pan', function(e) {
map.stop();
var mouseLocation = map.transform.pointLocation(e.point.add(e.offset));
map.transform.setLocationAtPoint(mouseLocation, e.point);
map.fire('move');
})
.on('panend', function(e) {
if (!e.inertia) {
map.fire('moveend');
} else {
// convert velocity to px/s & adjust for increased initial animation speed when easing out
var velocity = e.inertia.mult(1000 * inertiaLinearity),
speed = velocity.mag();
var maxSpeed = 4000; // px/s
if (speed >= maxSpeed) {
speed = maxSpeed;
velocity._unit()._mult(maxSpeed);
}
var deceleration = 8000, // px/s^2
duration = speed / (deceleration * inertiaLinearity),
offset = velocity.mult(-duration / 2).round();
map.panBy(offset, {
duration: duration * 1000,
easing: inertiaEasing,
noMoveStart: true
});
}
})
.on('zoom', function(e) {
// Scale by sigmoid of scroll wheel delta.
var scale = 2 / (1 + Math.exp(-Math.abs(e.delta / 100)));
if (e.delta < 0 && scale !== 0) scale = 1 / scale;
var fromScale = map.ease && isFinite(e.delta) ? map.ease.to : map.transform.scale,
duration = !isFinite(e.delta) ? 800 : 0;
map.zoomTo(map.transform.scaleZoom(fromScale * scale), {
duration: duration,
around: map.unproject(e.point)
});
})
.on('rotate', function(e) {
var center = map.transform.centerPoint, // Center of rotation
startToCenter = e.start.sub(center),
startToCenterDist = startToCenter.mag();
map.rotating = true;
// If the first click was too close to the center, move the center of rotation by 200 pixels
// in the direction of the click.
if (startToCenterDist < 200) {
center = e.start.add(new Point(-200, 0)._rotate(startToCenter.angle()));
}
var bearingDiff = e.prev.sub(center).angleWith(e.current.sub(center)) / Math.PI * 180;
map.transform.bearing = map.getBearing() - bearingDiff;
map.fire('move').fire('rotate');
window.clearTimeout(rotateEnd);
rotateEnd = window.setTimeout(function() {
map.rotating = false;
map._rerender();
}, 200);
})
.on('boxzoomstart', function(e) {
if (!box) {
box = DOM.create('div', 'mapboxgl-boxzoom', map.getContainer());
map.getContainer().classList.add('mapboxgl-crosshair');
map.fire('boxzoomstart');
DOM.disableDrag();
}
var minX = Math.min(e.start.x, e.current.x);
var maxX = Math.max(e.start.x, e.current.x);
var minY = Math.min(e.start.y, e.current.y);
var maxY = Math.max(e.start.y, e.current.y);
DOM.setTransform(box, 'translate(' + minX + 'px,' + minY + 'px)');
box.style.width = (maxX - minX) + 'px';
box.style.height = (maxY - minY) + 'px';
})
.on('boxzoomend', function(e) {
boxzoomFinish();
var bounds = new LatLngBounds(
map.unproject(e.start),
map.unproject(e.current)
);
map.fitBounds(bounds, { linear: true }).fire('boxzoomend', {
boxZoomBounds: bounds
});
})
.on('boxzoomcancel', boxzoomFinish);
}
},{"../geo/lat_lng_bounds":19,"../util/dom":88,"../util/util":96,"./interaction":80,"point-geometry":113}],79:[function(require,module,exports){
'use strict';
/*
* Adds positional coordinates to URL hashes. Passed as an option to the map object
*
* @class mapboxgl.Hash
* @returns {Hash} `this`
*/
module.exports = Hash;
var util = require('../util/util');
function Hash() {
util.bindAll([
'_onHashChange',
'_updateHash'
], this);
}
Hash.prototype = {
/* Map element to listen for coordinate changes
*
* @param {Object} map
* @returns {Hash} `this`
*/
addTo: function(map) {
this._map = map;
window.addEventListener('hashchange', this._onHashChange, false);
this._map.on('moveend', this._updateHash);
return this;
},
/* Removes hash
*
* @returns {Popup} `this`
*/
remove: function() {
window.removeEventListener('hashchange', this._onHashChange, false);
this._map.off('moveend', this._updateHash);
delete this._map;
return this;
},
_onHashChange: function() {
var loc = location.hash.replace('#', '').split('/');
if (loc.length >= 3) {
this._map.jumpTo({
center: [+loc[1], +loc[2]],
zoom: +loc[0],
bearing: +(loc[3] || 0)
});
return true;
}
return false;
},
_updateHash: function() {
var center = this._map.getCenter(),
zoom = this._map.getZoom(),
bearing = this._map.getBearing(),
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
hash = '#' + (Math.round(zoom * 100) / 100) +
'/' + center.lat.toFixed(precision) +
'/' + center.lng.toFixed(precision) +
(bearing ? '/' + (Math.round(bearing * 10) / 10) : '');
window.history.replaceState('', '', hash);
}
};
},{"../util/util":96}],80:[function(require,module,exports){
'use strict';
var Evented = require('../util/evented');
var browser = require('../util/browser');
var Point = require('point-geometry');
module.exports = Interaction;
/**
* Mouse event
*
* @event Map#mousemove
* @type {Object}
* @property {Point} point the pixel location of the event
* @property {Event} originalEvent the original DOM event
*/
/**
* Double click event.
*
* @event Map#dblclick
* @type {Object}
* @property {Point} point the pixel location of the event
*/
/**
* Pan event
*
* @event Map#pan
* @type {Object}
* @property {Point} point the pixel location of the event
* @property {Point} offset a point representing the movement from the previous map location to the current one.
*/
/**
* Pan end event
*
* @event Map#panend
* @type {Object}
* @property {number} velocity a measure of how much inertia was recorded in this pan motion
*/
function Interaction(el) {
var interaction = this;
if (!el) return;
var rotating = false,
panned = false,
boxzoom = false,
firstPos = null,
pos = null,
inertia = null,
now;
function mousePos(e) {
var rect = el.getBoundingClientRect();
return new Point(
e.clientX - rect.left - el.clientLeft,
e.clientY - rect.top - el.clientTop);
}
el.addEventListener('contextmenu', function(ev) {
rotating = true;
firstPos = pos = mousePos(ev);
ev.preventDefault();
}, false);
el.addEventListener('mousedown', onmousedown, false);
document.addEventListener('mouseup', onmouseup, false);
document.addEventListener('mousemove', onmousemove, false);
el.addEventListener('click', onclick, false);
scrollwheel(zoom);
el.addEventListener('dblclick', ondoubleclick, false);
window.addEventListener('resize', resize, false);
el.addEventListener('keydown', keydown, false);
function zoom(type, delta, point) {
interaction.fire('zoom', {
source: type,
delta: delta,
point: point
});
inertia = null;
now = null;
}
function click(point, ev) {
interaction.fire('click', {point: point, originalEvent: ev});
}
function mousemove(point, ev) {
interaction.fire('mousemove', {point: point, originalEvent: ev});
}
function pan(point) {
if (pos) {
var offset = pos.sub(point);
interaction.fire('pan', {offset: offset, point: point});
// add an averaged version of this movement to the inertia vector
if (inertia) {
var duration = Date.now() - now;
// sometimes it's 0 after some erratic paning
if (duration) {
var time = duration + now;
inertia.push([time, point]);
while (inertia.length > 2 && time - inertia[0][0] > 100) inertia.shift();
}
} else {
inertia = [];
}
now = Date.now();
pos = point;
}
}
function resize() {
interaction.fire('resize');
}
function keydown(ev) {
if (boxzoom && ev.keyCode === 27) {
interaction.fire('boxzoomcancel');
boxzoom = false;
}
interaction.fire('keydown', ev);
}
function rotate(point) {
if (pos) {
interaction.fire('rotate', {
start: firstPos,
prev: pos,
current: point
});
pos = point;
}
}
function doubleclick(point, ev) {
interaction.fire('dblclick', {
point: point,
originalEvent: ev
});
}
function onmousedown(ev) {
firstPos = pos = mousePos(ev);
interaction.fire('down');
if (ev.shiftKey || ((ev.which === 1) && (ev.button === 1))) {
boxzoom = true;
}
}
function onmouseup(ev) {
panned = pos && firstPos && (pos.x !== firstPos.x || pos.y !== firstPos.y);
rotating = false;
pos = null;
if (boxzoom) {
interaction.fire('boxzoomend', {
start: firstPos,
current: mousePos(ev)
});
boxzoom = false;
} else if (inertia && inertia.length >= 2 && now > Date.now() - 100) {
var last = inertia[inertia.length - 1],
first = inertia[0],
velocity = last[1].sub(first[1]).div(last[0] - first[0]);
interaction.fire('panend', {inertia: velocity});
} else if (pos) {
interaction.fire('panend');
}
inertia = null;
now = null;
}
function onmousemove(ev) {
var point = mousePos(ev);
if (boxzoom) {
interaction.fire('boxzoomstart', {
start: firstPos,
current: point
});
} else if (rotating) {
rotate(point);
} else if (pos) {
pan(point);
} else {
var target = ev.toElement || ev.target;
while (target && target !== el && target.parentNode) target = target.parentNode;
if (target === el) {
mousemove(point, ev);
}
}
}
function onclick(ev) {
if (!panned) click(mousePos(ev), ev);
}
function ondoubleclick(ev) {
doubleclick(mousePos(ev), ev);
zoom('wheel', Infinity * (ev.shiftKey ? -1 : 1), mousePos(ev));
ev.preventDefault();
}
function scrollwheel(callback) {
var firefox = /Firefox/i.test(navigator.userAgent);
var safari = /Safari/i.test(navigator.userAgent) && !/Chrom(ium|e)/i.test(navigator.userAgent);
var time = window.performance || Date;
el.addEventListener('wheel', wheel, false);
el.addEventListener('mousewheel', mousewheel, false);
var lastEvent = 0;
var type = null;
var typeTimeout = null;
var initialValue = null;
function scroll(value, ev) {
var stamp = time.now();
var timeDelta = stamp - lastEvent;
lastEvent = stamp;
var point = mousePos(ev);
if (value !== 0 && (value % 4.000244140625) === 0) {
// This one is definitely a mouse wheel event.
type = 'wheel';
// Normalize this value to match trackpad.
value = Math.floor(value / 4);
} else if (value !== 0 && Math.abs(value) < 4) {
// This one is definitely a trackpad event because it is so small.
type = 'trackpad';
} else if (timeDelta > 400) {
// This is likely a new scroll action.
type = null;
initialValue = value;
// Start a timeout in case this was a singular event, and dely it
// by up to 40ms.
typeTimeout = setTimeout(function() {
type = 'wheel';
callback(type, -initialValue, point);
}, 40);
} else if (type === null) {
// This is a repeating event, but we don't know the type of event
// just yet. If the delta per time is small, we assume it's a
// fast trackpad; otherwise we switch into wheel mode.
type = (Math.abs(timeDelta * value) < 200) ? 'trackpad' : 'wheel';
// Make sure our delayed event isn't fired again, because we
// accumulate the previous event (which was less than 40ms ago) into
// this event.
if (typeTimeout) {
clearTimeout(typeTimeout);
typeTimeout = null;
value += initialValue;
}
}
// Slow down zoom if shift key is held for more precise zooming
if (ev.shiftKey && value) value = value / 4;
// Only fire the callback if we actually know what type of scrolling
// device the user uses.
if (type !== null) {
callback(type, -value, point);
}
}
function wheel(e) {
var deltaY = e.deltaY;
// Firefox doubles the values on retina screens...
if (firefox && e.deltaMode === window.WheelEvent.DOM_DELTA_PIXEL) deltaY /= browser.devicePixelRatio;
if (e.deltaMode === window.WheelEvent.DOM_DELTA_LINE) deltaY *= 40;
scroll(deltaY, e);
e.preventDefault();
}
function mousewheel(e) {
var deltaY = -e.wheelDeltaY;
if (safari) deltaY = deltaY / 3;
scroll(deltaY, e);
e.preventDefault();
}
}
}
Interaction.prototype = Object.create(Evented);
},{"../util/browser":85,"../util/evented":90,"point-geometry":113}],81:[function(require,module,exports){
'use strict';
var Canvas = require('../util/canvas');
var util = require('../util/util');
var browser = require('../util/browser');
var Evented = require('../util/evented');
var DOM = require('../util/dom');
var Style = require('../style/style');
var AnimationLoop = require('../style/animation_loop');
var Painter = require('../render/painter');
var Transform = require('../geo/transform');
var Hash = require('./hash');
var Handlers = require('./handlers');
var Camera = require('./camera');
var LatLng = require('../geo/lat_lng');
var LatLngBounds = require('../geo/lat_lng_bounds');
var Point = require('point-geometry');
var Attribution = require('./control/attribution');
/**
* Creates a map instance.
* @class Map
* @param {Object} options
* @param {String} options.container HTML element to initialize the map in (or element id as string)
* @param {Number} [options.minZoom=0] Minimum zoom of the map
* @param {Number} [options.maxZoom=20] Maximum zoom of the map
* @param {Object} options.style Map style and data source definition (either a JSON object or a JSON URL), described in the [style reference](https://mapbox.com/mapbox-gl-style-spec/)
* @param {Boolean} [options.hash=false] If `true`, the map will track and update the page URL according to map position
* @param {Boolean} [options.interactive=true] If `false`, no mouse, touch, or keyboard listeners are attached to the map, so it will not respond to input
* @param {Array} options.classes Style class names with which to initialize the map
* @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.
* @param {Boolean} [options.preserveDrawingBuffer=false] If `true`, The maps canvas can be exported to a PNG using `map.getCanvas().toDataURL();`. This is false by default as a performance optimization.
* @example
* var map = new mapboxgl.Map({
* container: 'map',
* center: [37.772537, -122.420679],
* zoom: 13,
* style: style_object,
* hash: true
* });
*/
var Map = module.exports = function(options) {
options = this.options = util.inherit(this.options, options);
this.animationLoop = new AnimationLoop();
this.transform = new Transform(options.minZoom, options.maxZoom);
if (options.maxBounds) {
var b = LatLngBounds.convert(options.maxBounds);
this.transform.latRange = [b.getSouth(), b.getNorth()];
this.transform.lngRange = [b.getWest(), b.getEast()];
}
util.bindAll([
'_forwardStyleEvent',
'_forwardSourceEvent',
'_forwardLayerEvent',
'_forwardTileEvent',
'_onStyleLoad',
'_onStyleChange',
'_onSourceAdd',
'_onSourceRemove',
'_onSourceUpdate',
'update',
'render'
], this);
this._setupContainer();
this._setupPainter();
this.on('move', this.update);
this.on('zoom', this.update.bind(this, true));
this.on('moveend', function() {
this.animationLoop.set(300); // text fading
this._rerender();
}.bind(this));
this.handlers = options.interactive && new Handlers(this);
this._hash = options.hash && (new Hash()).addTo(this);
// don't set position from options if set through hash
if (!this._hash || !this._hash._onHashChange()) {
this.jumpTo(options);
}
this.sources = {};
this.stacks = {};
this._classes = {};
this.resize();
if (options.classes) this.setClasses(options.classes);
if (options.style) this.setStyle(options.style);
if (options.attributionControl) this.addControl(new Attribution());
};
util.extend(Map.prototype, Evented);
util.extend(Map.prototype, Camera.prototype);
util.extend(Map.prototype, /** @lends Map.prototype */{
options: {
center: [0, 0],
zoom: 0,
bearing: 0,
pitch: 0,
minZoom: 0,
maxZoom: 20,
interactive: true,
hash: false,
attributionControl: true,
failIfMajorPerformanceCaveat: false,
preserveDrawingBuffer: false
},
addControl: function(control) {
control.addTo(this);
return this;
},
/**
* @typedef {Object} [styleOptions]
* @param {Boolean} [styleOptions.transition=true]
*/
/**
* Adds a style class to a map
*
* @param {string} klass name of style class
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
addClass: function(klass, options) {
if (this._classes[klass]) return;
this._classes[klass] = true;
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Removes a style class from a map
*
* @param {string} klass name of style class
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
removeClass: function(klass, options) {
if (!this._classes[klass]) return;
delete this._classes[klass];
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Helper method to add more than one class
*
* @param {Array<string>} klasses An array of class names
* @param {styleOptions} options
* @fires change
* @returns {Map} `this`
*/
setClasses: function(klasses, options) {
this._classes = {};
for (var i = 0; i < klasses.length; i++) {
this._classes[klasses[i]] = true;
}
if (this.style) this.style._cascade(this._classes, options);
},
/**
* Check whether a style class is active
*
* @param {string} klass Name of style class
* @returns {boolean}
*/
hasClass: function(klass) {
return !!this._classes[klass];
},
/**
* Return an array of the current active style classes
*
* @returns {boolean}
*/
getClasses: function() {
return Object.keys(this._classes);
},
/**
* Detect the map's new width and height and resize it.
*
* @returns {Map} `this`
*/
resize: function() {
var width = 0, height = 0;
if (this._container) {
width = this._container.offsetWidth || 400;
height = this._container.offsetHeight || 300;
}
this._canvas.resize(width, height);
this.transform.width = width;
this.transform.height = height;
this.transform._constrain();
this.painter.resize(width, height);
return this
.fire('movestart')
.fire('move')
.fire('resize')
.fire('moveend');
},
/**
* Get the map's geographical bounds
*
* @returns {LatLngBounds}
*/
getBounds: function() {
return new LatLngBounds(
this.transform.pointLocation(new Point(0, 0)),
this.transform.pointLocation(this.transform.size));
},
/**
* Get pixel coordinates (relative to map container) given a geographical location
*
* @param {LatLng} latlng
* @returns {Object} `x` and `y` coordinates
*/
project: function(latlng) {
return this.transform.locationPoint(LatLng.convert(latlng));
},
/**
* Get geographical coordinates given pixel coordinates
*
* @param {Array<number>} point [x, y] pixel coordinates
* @returns {LatLng}
*/
unproject: function(point) {
return this.transform.pointLocation(Point.convert(point));
},
/**
* Get all features at a point ([x, y])
*
* @param {Array<number>} point [x, y] pixel coordinates
* @param {Object} params
* @param {number} [params.radius=0] Optional. Radius in pixels to search in
* @param {string} params.layer Optional. Only return features from a given layer
* @param {string} params.type Optional. Either `raster` or `vector`
* @param {featuresAtCallback} callback function that returns the response
*
* @callback featuresAtCallback
* @param {Object|null} err Error _If any_
* @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`
*
* @returns {Map} `this`
*
* @example
* map.featuresAt([10, 20], { radius: 10 }, function(err, features) {
* console.log(features);
* });
*/
featuresAt: function(point, params, callback) {
var coord = this.transform.pointCoordinate(Point.convert(point));
this.style.featuresAt(coord, params, callback);
return this;
},
/**
* Replaces the map's style object
*
* @param {Object} style A style object formatted as JSON
* @returns {Map} `this`
*/
setStyle: function(style) {
if (this.style) {
this.style
.off('load', this._onStyleLoad)
.off('error', this._forwardStyleEvent)
.off('change', this._onStyleChange)
.off('source.add', this._onSourceAdd)
.off('source.remove', this._onSourceRemove)
.off('source.load', this._onSourceUpdate)
.off('source.error', this._forwardSourceEvent)
.off('source.change', this._onSourceUpdate)
.off('layer.add', this._forwardLayerEvent)
.off('layer.remove', this._forwardLayerEvent)
.off('tile.add', this._forwardTileEvent)
.off('tile.remove', this._forwardTileEvent)
.off('tile.load', this.update)
.off('tile.error', this._forwardTileEvent)
._remove();
this.off('rotate', this.style._redoPlacement);
this.off('pitch', this.style._redoPlacement);
}
if (!style) {
this.style = null;
return this;
} else if (style instanceof Style) {
this.style = style;
} else {
this.style = new Style(style, this.animationLoop);
}
this.style
.on('load', this._onStyleLoad)
.on('error', this._forwardStyleEvent)
.on('change', this._onStyleChange)
.on('source.add', this._onSourceAdd)
.on('source.remove', this._onSourceRemove)
.on('source.load', this._onSourceUpdate)
.on('source.error', this._forwardSourceEvent)
.on('source.change', this._onSourceUpdate)
.on('layer.add', this._forwardLayerEvent)
.on('layer.remove', this._forwardLayerEvent)
.on('tile.add', this._forwardTileEvent)
.on('tile.remove', this._forwardTileEvent)
.on('tile.load', this.update)
.on('tile.error', this._forwardTileEvent);
this.on('rotate', this.style._redoPlacement);
this.on('pitch', this.style._redoPlacement);
return this;
},
/**
* Add a source to the map style.
*
* @param {string} id ID of the source. Must not be used by any existing source.
* @param {Object} source source specification, following the
* [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)
* @fires source.add
* @returns {Map} `this`
*/
addSource: function(id, source) {
this.style.addSource(id, source);
return this;
},
/**
* Remove an existing source from the map style.
*
* @param {string} id ID of the source to remove
* @fires source.remove
* @returns {Map} `this`
*/
removeSource: function(id) {
this.style.removeSource(id);
return this;
},
/**
* Return the style source object with the given `id`.
*
* @param {string} id source ID
* @returns {Object}
*/
getSource: function(id) {
return this.style.getSource(id);
},
/**
* Add a layer to the map style. The layer will be inserted before the layer with
* ID `before`, or appended if `before` is omitted.
* @param {StyleLayer|Object} layer
* @param {string=} before ID of an existing layer to insert before
* @fires layer.add
* @returns {Map} `this`
*/
addLayer: function(layer, before) {
this.style.addLayer(layer, before);
this.style._cascade(this._classes);
return this;
},
/**
* Remove the layer with the given `id` from the map. Any layers which refer to the
* specified layer via a `ref` property are also removed.
*
* @param {string} id layer id
* @fires layer.remove
* @returns {Map} this
*/
removeLayer: function(id) {
this.style.removeLayer(id);
this.style._cascade(this._classes);
return this;
},
/**
* Set the filter for a given style layer.
*
* @param {string} layer ID of a layer
* @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)
* @returns {Map} `this`
*/
setFilter: function(layer, filter) {
this.style.setFilter(layer, filter);
return this;
},
/**
* Get the filter for a given style layer.
*
* @param {string} layer ID of a layer
* @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)
*/
getFilter: function(layer) {
return this.style.getFilter(layer);
},
/**
* Set the value of a paint property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a paint property
* @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)
* @param {string=} klass optional class specifier for the property
* @returns {Map} `this`
*/
setPaintProperty: function(layer, name, value, klass) {
this.style.setPaintProperty(layer, name, value, klass);
this.style._cascade(this._classes);
this.update(true);
return this;
},
/**
* Get the value of a paint property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a paint property
* @param {string=} klass optional class specifier for the property
* @returns {*} value for the paint propery
*/
getPaintProperty: function(layer, name, klass) {
return this.style.getPaintProperty(layer, name, klass);
},
/**
* Set the value of a layout property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a layout property
* @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)
* @returns {Map} `this`
*/
setLayoutProperty: function(layer, name, value) {
this.style.setLayoutProperty(layer, name, value);
return this;
},
/**
* Get the value of a layout property in a given style layer.
*
* @param {string} layer ID of a layer
* @param {string} name name of a layout property
* @param {string=} klass optional class specifier for the property
* @returns {*} value for the layout propery
*/
getLayoutProperty: function(layer, name) {
return this.style.getLayoutProperty(layer, name);
},
/**
* Get the Map's container as an HTML element
* @returns {HTMLElement} container
*/
getContainer: function() {
return this._container;
},
/**
* Get the container for the map `canvas` element.
*
* If you want to add non-GL overlays to the map, you should append them to this element. This
* is the element to which event bindings for map interactivity such as panning and zooming are
* attached. It will receive bubbled events for child elements such as the `canvas`, but not for
* map controls.
*
* @returns {HTMLElement} container
*/
getCanvasContainer: function() {
return this._canvasContainer;
},
/**
* Get the Map's canvas as an HTML canvas
* @returns {HTMLElement} canvas
*/
getCanvas: function() {
return this._canvas.getElement();
},
_setupContainer: function() {
var id = this.options.container;
var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;
container.classList.add('mapboxgl-map');
var canvasContainer = this._canvasContainer = DOM.create('div', 'mapboxgl-canvas-container', container);
if (this.options.interactive) {
canvasContainer.classList.add('mapboxgl-interactive');
}
this._canvas = new Canvas(this, canvasContainer);
var controlContainer = DOM.create('div', 'mapboxgl-control-container', container);
var corners = this._controlCorners = {};
['top-left', 'top-right', 'bottom-left', 'bottom-right'].forEach(function (pos) {
corners[pos] = DOM.create('div', 'mapboxgl-ctrl-' + pos, controlContainer);
});
},
_setupPainter: function() {
var gl = this._canvas.getWebGLContext({
failIfMajorPerformanceCaveat: this.options.failIfMajorPerformanceCaveat,
preserveDrawingBuffer: this.options.preserveDrawingBuffer
});
if (!gl) {
console.error('Failed to initialize WebGL');
return;
}
this.painter = new Painter(gl, this.transform);
},
_contextLost: function(event) {
event.preventDefault();
if (this._frameId) {
browser.cancelFrame(this._frameId);
}
},
_contextRestored: function() {
this._setupPainter();
this.resize();
this.update();
},
/**
* Is this map fully loaded? If the style isn't loaded
* or it has a change to the sources or style that isn't
* propagated to its style, return false.
*
* @returns {boolean} whether the map is loaded
*/
loaded: function() {
if (this._styleDirty || this._sourcesDirty)
return false;
if (this.style && !this.style.loaded())
return false;
return true;
},
/**
* Update this map's style and re-render the map.
*
* @param {Object} updateStyle new style
* @returns {Map} this
*/
update: function(updateStyle) {
if (!this.style) return this;
this._styleDirty = this._styleDirty || updateStyle;
this._sourcesDirty = true;
this._rerender();
return this;
},
/**
* Call when a (re-)render of the map is required, e.g. when the
* user panned or zoomed,f or new data is available.
* @returns {Map} this
*/
render: function() {
if (this.style && this._styleDirty) {
this._styleDirty = false;
this.style._recalculate(this.transform.zoom);
}
if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {
this._sourcesDirty = false;
this._sourcesDirtyTimeout = setTimeout(function() {
this._sourcesDirtyTimeout = null;
}.bind(this), 50);
this.style._updateSources(this.transform);
}
this.painter.render(this.style, {
debug: this.debug,
vertices: this.vertices,
rotating: this.rotating,
zooming: this.zooming
});
this.fire('render');
if (this.loaded() && !this._loaded) {
this._loaded = true;
this.fire('load');
}
this._frameId = null;
if (!this.animationLoop.stopped()) {
this._styleDirty = true;
}
if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {
this._rerender();
}
return this;
},
/**
* Destroys the map's underlying resources, including web workers.
* @returns {Map} this
*/
remove: function() {
if (this._hash) this._hash.remove();
browser.cancelFrame(this._frameId);
clearTimeout(this._sourcesDirtyTimeout);
this.setStyle(null);
return this;
},
_rerender: function() {
if (this.style && !this._frameId) {
this._frameId = browser.frame(this.render);
}
},
_forwardStyleEvent: function(e) {
this.fire('style.' + e.type, util.extend({style: e.target}, e));
},
_forwardSourceEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_forwardLayerEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_forwardTileEvent: function(e) {
this.fire(e.type, util.extend({style: e.target}, e));
},
_onStyleLoad: function(e) {
this.style._cascade(this._classes, {transition: false});
this._forwardStyleEvent(e);
},
_onStyleChange: function(e) {
this.update(true);
this._forwardStyleEvent(e);
},
_onSourceAdd: function(e) {
var source = e.source;
if (source.onAdd)
source.onAdd(this);
this._forwardSourceEvent(e);
},
_onSourceRemove: function(e) {
var source = e.source;
if (source.onRemove)
source.onRemove(this);
this._forwardSourceEvent(e);
},
_onSourceUpdate: function(e) {
this.update();
this._forwardSourceEvent(e);
}
});
util.extendAll(Map.prototype, {
/**
* Enable debugging mode
*
* @name debug
* @memberof Map
* @type {boolean}
*/
_debug: false,
get debug() { return this._debug; },
set debug(value) { this._debug = value; this.update(); },
/**
* Show collision boxes: useful for debugging label placement
* in styles.
*
* @name collisionDebug
* @memberof Map
* @type {boolean}
*/
_collisionDebug: false,
get collisionDebug() { return this._collisionDebug; },
set collisionDebug(value) {
this._collisionDebug = value;
for (var i in this.style.sources) {
if (this.style.sources[i].reload) {
this.style.sources[i].reload();
}
}
this.update();
},
/**
* Enable continuous repaint to analyze performance
*
* @name repaint
* @memberof Map
* @type {boolean}
*/
_repaint: false,
get repaint() { return this._repaint; },
set repaint(value) { this._repaint = value; this.update(); },
// show vertices
_vertices: false,
get vertices() { return this._vertices; },
set vertices(value) { this._vertices = value; this.update(); }
});
},{"../geo/lat_lng":18,"../geo/lat_lng_bounds":19,"../geo/transform":20,"../render/painter":34,"../style/animation_loop":47,"../style/style":52,"../util/browser":85,"../util/canvas":86,"../util/dom":88,"../util/evented":90,"../util/util":96,"./camera":74,"./control/attribution":75,"./handlers":78,"./hash":79,"point-geometry":113}],82:[function(require,module,exports){
'use strict';
module.exports = Popup;
var util = require('../util/util');
var Evented = require('../util/evented');
var DOM = require('../util/dom');
var LatLng = require('../geo/lat_lng');
/**
* Creates a popup component
* @class Popup
* @param {Object} options
* @param {Boolean} options.closeButton
* @param {Boolean} options.closeOnClick
* @example
* var tooltip = new mapboxgl.Popup()
* .setLatLng(map.unproject(e.point))
* .setHTML("<h1>Hello World!</h1>")
* .addTo(map);
*/
function Popup(options) {
util.setOptions(this, options);
util.bindAll([
'_updatePosition',
'_onClickClose'],
this);
}
Popup.prototype = util.inherit(Evented, /** @lends Popup.prototype */{
options: {
closeButton: true,
closeOnClick: true
},
/**
* Attaches the popup to a map
* @param {Map} map
* @returns {Popup} `this`
*/
addTo: function(map) {
this._map = map;
this._map.on('move', this._updatePosition);
if (this.options.closeOnClick) {
this._map.on('click', this._onClickClose);
}
this._update();
return this;
},
/**
* Removes the popup from the map
* @example
* var popup = new mapboxgl.Popup().addTo(map);
* popup.remove();
* @returns {Popup} `this`
*/
remove: function() {
if (this._container) {
this._container.parentNode.removeChild(this._container);
}
if (this._map) {
this._map.off('move', this._updatePosition);
this._map.off('click', this._onClickClose);
delete this._map;
}
return this;
},
/**
* Get the current coordinates of popup element relative to map
* @returns {LatLng}
*/
getLatLng: function() {
return this._latLng;
},
/**
* Set the coordinates of a popup element to a map
* @param {LatLng} latlng
* @returns {Popup} `this`
*/
setLatLng: function(latlng) {
this._latLng = LatLng.convert(latlng);
this._update();
return this;
},
/**
* Fill a popup element with text only content
* @param {string} text
* @returns {Popup} `this`
*/
setText: function(text) {
this._content = document.createTextNode(text);
this._updateContent();
return this;
},
/**
* Fill a popup element with HTML content
* @param {string} html
* @returns {Popup} `this`
*/
setHTML: function(html) {
this._content = document.createDocumentFragment();
var temp = document.createElement('body'), child;
temp.innerHTML = html;
while (true) {
child = temp.firstChild;
if (!child) break;
this._content.appendChild(child);
}
this._updateContent();
return this;
},
_update: function() {
if (!this._map) { return; }
if (!this._container) {
this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());
this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);
this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);
if (this.options.closeButton) {
this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);
this._closeButton.innerHTML = '×';
this._closeButton.addEventListener('click', this._onClickClose);
}
}
this._updateContent();
this._updatePosition();
},
_updateContent: function() {
if (!this._content || !this._container) { return; }
var node = this._wrapper;
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
node.appendChild(this._closeButton);
node.appendChild(this._content);
},
_updatePosition: function() {
if (!this._latLng || !this._container) { return; }
var pos = this._map.project(this._latLng).round(),
anchor = this.options.anchor;
if (!anchor) {
var width = this._container.offsetWidth,
height = this._container.offsetHeight;
if (pos.y < height) {
anchor = ['top'];
} else if (pos.y > this._map.transform.height - height) {
anchor = ['bottom'];
} else {
anchor = [];
}
if (pos.x < width / 2) {
anchor.push('left');
} else if (pos.x > this._map.transform.width - width / 2) {
anchor.push('right');
}
if (anchor.length === 0) {
anchor = 'bottom';
} else {
anchor = anchor.join('-');
}
this.options.anchor = anchor;
}
var anchorTranslate = {
'top': 'translate(-50%,0)',
'top-left': 'translate(0,0)',
'top-right': 'translate(-100%,0)',
'bottom': 'translate(-50%,-100%)',
'bottom-left': 'translate(0,-100%)',
'bottom-right': 'translate(-100%,-100%)',
'left': 'translate(0,-50%)',
'right': 'translate(-100%,-50%)'
};
var classList = this._container.classList;
for (var key in anchorTranslate) {
classList.remove('mapboxgl-popup-anchor-' + key);
}
classList.add('mapboxgl-popup-anchor-' + anchor);
DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');
},
_onClickClose: function() {
this.remove();
}
});
},{"../geo/lat_lng":18,"../util/dom":88,"../util/evented":90,"../util/util":96}],83:[function(require,module,exports){
'use strict';
module.exports = Actor;
/**
* An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model)
* that maintains the relationship between asynchronous tasks and the objects
* that spin them off - in this case, tasks like parsing parts of styles,
* owned by the styles
*
* @param {WebWorker} target
* @param {WebWorker} parent
* @private
*/
function Actor(target, parent) {
this.target = target;
this.parent = parent;
this.callbacks = {};
this.callbackID = 0;
this.receive = this.receive.bind(this);
this.target.addEventListener('message', this.receive, false);
}
Actor.prototype.receive = function(message) {
var data = message.data,
callback;
if (data.type === '<response>') {
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
callback(data.error || null, data.data);
} else if (typeof data.id !== 'undefined') {
var id = data.id;
this.parent[data.type](data.data, function(err, data, buffers) {
this.postMessage({
type: '<response>',
id: String(id),
error: err ? String(err) : null,
data: data
}, buffers);
}.bind(this));
} else {
this.parent[data.type](data.data);
}
};
Actor.prototype.send = function(type, data, callback, buffers) {
var id = null;
if (callback) this.callbacks[id = this.callbackID++] = callback;
this.postMessage({ type: type, id: String(id), data: data }, buffers);
};
/**
* Wrapped postMessage API that abstracts around IE's lack of
* `transferList` support.
*
* @param {Object} message
* @param {Object} transferList
*/
Actor.prototype.postMessage = function(message, transferList) {
try {
this.target.postMessage(message, transferList);
} catch (e) {
this.target.postMessage(message); // No support for transferList on IE
}
};
},{}],84:[function(require,module,exports){
'use strict';
exports.getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onerror = function(e) {
callback(e);
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
var data;
try {
data = JSON.parse(xhr.response);
} catch (err) {
return callback(err);
}
callback(null, data);
} else {
callback(new Error(xhr.statusText));
}
};
xhr.send();
return xhr;
};
exports.getArrayBuffer = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onerror = function(e) {
callback(e);
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
callback(null, xhr.response);
} else {
callback(new Error(xhr.statusText));
}
};
xhr.send();
return xhr;
};
exports.getImage = function(url, callback) {
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function() {
callback(null, img);
};
img.src = url;
img.getData = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0);
return context.getImageData(0, 0, img.width, img.height).data;
};
return img;
};
exports.getVideo = function(urls, callback) {
var video = document.createElement('video');
video.crossOrigin = 'Anonymous';
video.onloadstart = function() {
callback(null, video);
};
for (var i = 0; i < urls.length; i++) {
var s = document.createElement('source');
s.src = urls[i];
video.appendChild(s);
}
video.getData = function() { return video; };
return video;
};
},{}],85:[function(require,module,exports){
'use strict';
var Canvas = require('./canvas');
var frame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
exports.frame = function(fn) {
return frame(fn);
};
var cancel = window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame;
exports.cancelFrame = function(id) {
cancel(id);
};
exports.timed = function (fn, dur, ctx) {
if (!dur) {
fn.call(ctx, 1);
return null;
}
var abort = false,
start = window.performance ? window.performance.now() : Date.now();
function tick(now) {
if (abort) return;
if (!window.performance) now = Date.now();
if (now >= start + dur) {
fn.call(ctx, 1);
} else {
fn.call(ctx, (now - start) / dur);
exports.frame(tick);
}
}
exports.frame(tick);
return function() { abort = true; };
};
/**
* Test whether the basic JavaScript and DOM features required for Mapbox GL are present.
* @param {Object} options
* @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.
* @return {Boolean} Returns true if Mapbox GL should be expected to work, and false if not.
*/
exports.supported = function(options) {
var supports = [
function() { return typeof window !== 'undefined'; },
function() { return typeof document !== 'undefined'; },
function () {
return !!(Array.prototype &&
Array.prototype.every &&
Array.prototype.filter &&
Array.prototype.forEach &&
Array.prototype.indexOf &&
Array.prototype.lastIndexOf &&
Array.prototype.map &&
Array.prototype.some &&
Array.prototype.reduce &&
Array.prototype.reduceRight &&
Array.isArray);
},
function() {
return !!(Function.prototype && Function.prototype.bind) &&
!!(Object.keys &&
Object.create &&
Object.getPrototypeOf &&
Object.getOwnPropertyNames &&
Object.isSealed &&
Object.isFrozen &&
Object.isExtensible &&
Object.getOwnPropertyDescriptor &&
Object.defineProperty &&
Object.defineProperties &&
Object.seal &&
Object.freeze &&
Object.preventExtensions);
},
function() {
return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON;
},
function() {
return new Canvas().supportsWebGLContext((options && options.failIfMajorPerformanceCaveat) || false);
},
function() { return 'Worker' in window; }
];
for (var i = 0; i < supports.length; i++) {
if (!supports[i]()) return false;
}
return true;
};
exports.hardwareConcurrency = navigator.hardwareConcurrency || 8;
Object.defineProperty(exports, 'devicePixelRatio', {
get: function() { return window.devicePixelRatio; }
});
},{"./canvas":86}],86:[function(require,module,exports){
'use strict';
var util = require('../util');
module.exports = Canvas;
function Canvas(parent, container) {
this.canvas = document.createElement('canvas');
if (parent && container) {
this.canvas.style.position = 'absolute';
this.canvas.classList.add('mapboxgl-canvas');
this.canvas.addEventListener('webglcontextlost', parent._contextLost.bind(parent), false);
this.canvas.addEventListener('webglcontextrestored', parent._contextRestored.bind(parent), false);
this.canvas.setAttribute('tabindex', 0);
container.appendChild(this.canvas);
}
}
Canvas.prototype.resize = function(width, height) {
var pixelRatio = window.devicePixelRatio || 1;
// Request the required canvas size taking the pixelratio into account.
this.canvas.width = pixelRatio * width;
this.canvas.height = pixelRatio * height;
// Maintain the same canvas size, potentially downscaling it for HiDPI displays
this.canvas.style.width = width + 'px';
this.canvas.style.height = height + 'px';
};
var requiredContextAttributes = {
antialias: false,
alpha: true,
stencil: true,
depth: false
};
Canvas.prototype.getWebGLContext = function(attributes) {
attributes = util.extend({}, attributes, requiredContextAttributes);
return this.canvas.getContext('webgl', attributes) ||
this.canvas.getContext('experimental-webgl', attributes);
};
Canvas.prototype.supportsWebGLContext = function(failIfMajorPerformanceCaveat) {
var attributes = util.extend({
failIfMajorPerformanceCaveat: failIfMajorPerformanceCaveat
}, requiredContextAttributes);
if ('probablySupportsContext' in this.canvas) {
return this.canvas.probablySupportsContext('webgl', attributes) ||
this.canvas.probablySupportsContext('experimental-webgl', attributes);
} else if ('supportsContext' in this.canvas) {
return this.canvas.supportsContext('webgl', attributes) ||
this.canvas.supportsContext('experimental-webgl', attributes);
}
return !!window.WebGLRenderingContext && !!this.getWebGLContext(failIfMajorPerformanceCaveat);
};
Canvas.prototype.getElement = function() {
return this.canvas;
};
},{"../util":96}],87:[function(require,module,exports){
'use strict';
var Actor = require('../actor');
var WebWorkify = require('webworkify');
module.exports = Dispatcher;
function Dispatcher(length, parent) {
this.actors = [];
this.currentActor = 0;
for (var i = 0; i < length; i++) {
var worker = new WebWorkify(require('../../source/worker'));
var actor = new Actor(worker, parent);
actor.name = "Worker " + i;
this.actors.push(actor);
}
}
Dispatcher.prototype = {
broadcast: function(type, data) {
for (var i = 0; i < this.actors.length; i++) {
this.actors[i].send(type, data);
}
},
send: function(type, data, callback, targetID, buffers) {
if (typeof targetID !== 'number' || isNaN(targetID)) {
// Use round robin to send requests to web workers.
targetID = this.currentActor = (this.currentActor + 1) % this.actors.length;
}
this.actors[targetID].send(type, data, callback, buffers);
return targetID;
},
remove: function() {
for (var i = 0; i < this.actors.length; i++) {
this.actors[i].target.terminate();
}
this.actors = [];
}
};
},{"../../source/worker":45,"../actor":83,"webworkify":125}],88:[function(require,module,exports){
'use strict';
exports.create = function (tagName, className, container) {
var el = document.createElement(tagName);
if (className) el.className = className;
if (container) container.appendChild(el);
return el;
};
var docStyle = document.documentElement.style;
function testProp(props) {
for (var i = 0; i < props.length; i++) {
if (props[i] in docStyle) {
return props[i];
}
}
}
var selectProp = testProp(['userSelect', 'MozUserSelect', 'WebkitUserSelect', 'msUserSelect']),
userSelect;
exports.disableDrag = function () {
if (selectProp) {
userSelect = docStyle[selectProp];
docStyle[selectProp] = 'none';
}
};
exports.enableDrag = function () {
if (selectProp) {
docStyle[selectProp] = userSelect;
}
};
var transformProp = testProp(['transform', 'WebkitTransform']);
exports.setTransform = function(el, value) {
el.style[transformProp] = value;
};
// Suppress the next click, but only if it's immediate.
function suppressClick(e) {
e.preventDefault();
e.stopPropagation();
window.removeEventListener('click', suppressClick, true);
}
exports.suppressClick = function() {
window.addEventListener('click', suppressClick, true);
window.setTimeout(function() {
window.removeEventListener('click', suppressClick, true);
}, 0);
};
},{}],89:[function(require,module,exports){
'use strict';
module.exports = {
HTTP_URL: 'http://a.tiles.mapbox.com',
HTTPS_URL: 'https://a.tiles.mapbox.com',
FORCE_HTTPS: true,
REQUIRE_ACCESS_TOKEN: true
};
},{}],90:[function(require,module,exports){
'use strict';
var util = require('./util');
/**
* Methods mixed in to other classes for event capabilities.
* @mixin Evented
*/
var Evented = {
/**
* Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties
*
* @param {String} type Event type
* @param {Function} listener Function to be called when the event is fired
*/
on: function(type, fn) {
this._events = this._events || {};
this._events[type] = this._events[type] || [];
this._events[type].push(fn);
return this;
},
/**
* Remove a event listener
*
* @param {String} [type] Event type. If none is specified, remove all listeners
* @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed
*/
off: function(type, fn) {
if (!type) {
// clear all listeners if no arguments specified
delete this._events;
return this;
}
if (!this.listens(type)) return this;
if (fn) {
var idx = this._events[type].indexOf(fn);
if (idx >= 0) {
this._events[type].splice(idx, 1);
}
if (!this._events[type].length) {
delete this._events[type];
}
} else {
delete this._events[type];
}
return this;
},
/**
* Call a function once when an event has fired
*
* @param {String} type Event type.
* @param {Function} listener Function to be called once when the event is fired
*/
once: function(type, fn) {
var wrapper = function(data) {
this.off(type, wrapper);
fn.call(this, data);
}.bind(this);
this.on(type, wrapper);
return this;
},
/**
* Fire event of a given string type with the given data object
*
* @param {String} type The event name
* @param {Object} [data] Optional data passed down to the event object
* @returns {Boolean} Returns true if the object listens to an event of a particular type
*/
fire: function(type, data) {
if (!this.listens(type)) return this;
data = util.extend({}, data);
util.extend(data, {type: type, target: this});
// make sure adding/removing listeners inside other listeners won't cause infinite loop
var listeners = this._events[type].slice();
for (var i = 0; i < listeners.length; i++) {
listeners[i].call(this, data);
}
return this;
},
/**
* Check if an event is registered to a type
* @returns {Boolean} Returns true if the object listens to an event of a particular type
*/
listens: function(type) {
return !!(this._events && this._events[type]);
}
};
module.exports = Evented;
},{"./util":96}],91:[function(require,module,exports){
'use strict';
module.exports = Glyphs;
function Glyphs(pbf, end) {
this.stacks = pbf.readFields(readFontstacks, [], end);
}
function readFontstacks(tag, stacks, pbf) {
if (tag === 1) {
var fontstack = pbf.readMessage(readFontstack, {glyphs: {}});
stacks.push(fontstack);
}
}
function readFontstack(tag, fontstack, pbf) {
if (tag === 1) fontstack.name = pbf.readString();
else if (tag === 2) fontstack.range = pbf.readString();
else if (tag === 3) {
var glyph = pbf.readMessage(readGlyph, {});
fontstack.glyphs[glyph.id] = glyph;
}
}
function readGlyph(tag, glyph, pbf) {
if (tag === 1) glyph.id = pbf.readVarint();
else if (tag === 2) glyph.bitmap = pbf.readBytes();
else if (tag === 3) glyph.width = pbf.readVarint();
else if (tag === 4) glyph.height = pbf.readVarint();
else if (tag === 5) glyph.left = pbf.readSVarint();
else if (tag === 6) glyph.top = pbf.readSVarint();
else if (tag === 7) glyph.advance = pbf.readVarint();
}
},{}],92:[function(require,module,exports){
'use strict';
module.exports = interpolate;
function interpolate(a, b, t) {
return (a * (1 - t)) + (b * t);
}
interpolate.number = interpolate;
interpolate.vec2 = function(from, to, t) {
return [
interpolate(from[0], to[0], t),
interpolate(from[1], to[1], t)
];
};
/*
* Interpolate between two colors given as 4-element arrays.
*
* @param {Color} from
* @param {Color} to
* @param {Number} t interpolation factor between 0 and 1
* @returns {Color} interpolated color
*/
interpolate.color = function(from, to, t) {
return [
interpolate(from[0], to[0], t),
interpolate(from[1], to[1], t),
interpolate(from[2], to[2], t),
interpolate(from[3], to[3], t)
];
};
interpolate.array = function(from, to, t) {
return from.map(function(d, i) {
return interpolate(d, to[i], t);
});
};
},{}],93:[function(require,module,exports){
'use strict';
var config = require('./config');
var browser = require('./browser');
function normalizeURL(url, pathPrefix, accessToken) {
accessToken = accessToken || config.ACCESS_TOKEN;
if (!accessToken && config.REQUIRE_ACCESS_TOKEN) {
throw new Error('An API access token is required to use Mapbox GL. ' +
'See https://www.mapbox.com/developers/api/#access-tokens');
}
var https = config.FORCE_HTTPS ||
(typeof document !== 'undefined' && document.location.protocol === 'https:');
url = url.replace(/^mapbox:\/\//, (https ? config.HTTPS_URL : config.HTTP_URL) + pathPrefix);
url += url.indexOf('?') !== -1 ? '&access_token=' : '?access_token=';
if (config.REQUIRE_ACCESS_TOKEN) {
if (accessToken[0] === 's') {
throw new Error('Use a public access token (pk.*) with Mapbox GL JS, not a secret access token (sk.*). ' +
'See https://www.mapbox.com/developers/api/#access-tokens');
}
url += accessToken;
}
return url;
}
module.exports.normalizeStyleURL = function(url, accessToken) {
var user = url.match(/^mapbox:\/\/([^.]+)/);
if (!user)
return url;
return normalizeURL(url, '/styles/v1/' + user[1] + '/', accessToken);
};
module.exports.normalizeSourceURL = function(url, accessToken) {
if (!url.match(/^mapbox:\/\//))
return url;
url = normalizeURL(url + '.json', '/v4/', accessToken);
// TileJSON requests need a secure flag appended to their URLs so
// that the server knows to send SSL-ified resource references.
if (url.indexOf('https') === 0)
url += '&secure';
return url;
};
module.exports.normalizeGlyphsURL = function(url, accessToken) {
if (!url.match(/^mapbox:\/\//))
return url;
return normalizeURL(url, '/v4/', accessToken);
};
module.exports.normalizeTileURL = function(url, sourceUrl) {
if (!sourceUrl || !sourceUrl.match(/^mapbox:\/\//))
return url;
return url.replace(/\.((?:png|jpg)\d*)(?=$|\?)/, browser.devicePixelRatio >= 2 ? '@2x.$1' : '.$1');
};
},{"./browser":85,"./config":89}],94:[function(require,module,exports){
'use strict';
/*
* A [most-recently-used cache](http://en.wikipedia.org/wiki/Cache_algorithms)
* with hash lookup made possible by keeping a list of keys in parallel to
* an array of dictionary of values
*
* @param {number} max number of permitted values
* @param {Function} onRemove callback called with items when they expire
* @private
*/
module.exports = MRUCache;
function MRUCache(max, onRemove) {
this.max = max;
this.onRemove = onRemove;
this.reset();
}
/**
* Clear the cache
*
* @returns {MRUCache} this cache
*/
MRUCache.prototype.reset = function() {
for (var key in this.list) {
this.onRemove(this.list[key]);
}
this.list = {};
this.order = [];
return this;
};
/*
* Add a key, value combination to the cache, trimming its size if this pushes
* it over max length.
*
* @param {string} key lookup key for the item
* @param {*} data any value
*
* @returns {MRUCache} this cache
*/
MRUCache.prototype.add = function(key, data) {
this.list[key] = data;
this.order.push(key);
if (this.order.length > this.max) {
var removedData = this.get(this.order[0]);
if (removedData) this.onRemove(removedData);
}
return this;
};
/*
* Determine whether the value attached to `key` is present
*
* @param {string} key the key to be looked-up
* @returns {boolean} whether the cache has this value
*/
MRUCache.prototype.has = function(key) {
return key in this.list;
};
/*
* List all keys in the cache
*
* @returns {Array<string>} an array of keys in this cache.
*/
MRUCache.prototype.keys = function() {
return this.order;
};
/*
* Get the value attached to a specific key. If the key is not found,
* returns `null`
*
* @param {string} key the key to look up
* @returns {*} the data, or null if it isn't found
*/
MRUCache.prototype.get = function(key) {
if (!this.has(key)) { return null; }
var data = this.list[key];
delete this.list[key];
this.order.splice(this.order.indexOf(key), 1);
return data;
};
},{}],95:[function(require,module,exports){
'use strict';
module.exports = resolveTokens;
/**
* Replace tokens in a string template with values in an object
*
* @param {Object} properties a key/value relationship between tokens and replacements
* @param {string} text the template string
* @returns {string} the template with tokens replaced
* @private
*/
function resolveTokens(properties, text) {
return text.replace(/{([^{}()\[\]<>$=:;.,^]+)}/g, function(match, key) {
return key in properties ? properties[key] : '';
});
}
},{}],96:[function(require,module,exports){
'use strict';
var UnitBezier = require('unitbezier');
/**
* Given a value `t` that varies between 0 and 1, return
* an interpolation function that eases between 0 and 1 in a pleasing
* cubic in-out fashion.
*
* @param {number} t input
* @returns {number} input
*/
exports.easeCubicInOut = function (t) {
if (t <= 0) return 0;
if (t >= 1) return 1;
var t2 = t * t,
t3 = t2 * t;
return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75);
};
/**
* Given given (x, y), (x1, y1) control points for a bezier curve,
* return a function that interpolates along that curve.
*
* @param {number} p1x control point 1 x coordinate
* @param {number} p1y control point 1 y coordinate
* @param {number} p2x control point 2 x coordinate
* @param {number} p2y control point 2 y coordinate
* @returns {Function} interpolator: receives number value, returns
* number value.
*/
exports.bezier = function(p1x, p1y, p2x, p2y) {
var bezier = new UnitBezier(p1x, p1y, p2x, p2y);
return function(t) {
return bezier.solve(t);
};
};
/**
* A default bezier-curve powered easing function with
* control points (0.25, 0.1) and (0.25, 1)
*
* @param {number} t
* @returns {number} output
*/
exports.ease = exports.bezier(0.25, 0.1, 0.25, 1);
/**
* Given a four-element array of numbers that represents a color in
* RGBA, return a version for which the RGB components are multiplied
* by the A (alpha) component
*
* @param {Number<Array>} c color array
* @returns {Number<Array>} premultiplied color array
*/
exports.premultiply = function (c) {
c[0] *= c[3];
c[1] *= c[3];
c[2] *= c[3];
return c;
};
/**
* constrain n to the given range via min + max
*
* @param {Number} n value
* @param {Number} min the minimum value to be returned
* @param {Number} max the maximum value to be returned
* @returns {Number} the clamped value
*/
exports.clamp = function (n, min, max) {
return Math.min(max, Math.max(min, n));
};
/*
* constrain n to the given range via modular arithmetic
* @param {Number} n
* @param {Number} min
* @param {Number} max
* @returns {Number} constrained number
*/
exports.wrap = function (n, min, max) {
var d = max - min;
return n === max ? n : ((n - min) % d + d) % d + min;
};
/*
* return the first non-null and non-undefined argument to this function.
* @returns {*} argument
*/
exports.coalesce = function() {
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (arg !== null && arg !== undefined)
return arg;
}
};
/*
* Call an asynchronous function on an array of arguments,
* calling `callback` once all calls complete.
*
* @param {Array<*>} array input to each call of the async function.
* @param {Function} fn an async function with signature (data, callback)
* @param {Function} callback a callback run after all async work is done.
* called with no arguments
* @returns {undefined}
*/
exports.asyncEach = function (array, fn, callback) {
var remaining = array.length;
if (remaining === 0) return callback();
function check() { if (--remaining === 0) callback(); }
for (var i = 0; i < array.length; i++) fn(array[i], check);
};
/*
* Compute the difference between the keys in one object and the keys
* in another object.
*
* @param {Object} obj
* @param {Object} other
* @returns {Array<string>} keys difference
*/
exports.keysDifference = function (obj, other) {
var difference = [];
for (var i in obj) {
if (!(i in other)) {
difference.push(i);
}
}
return difference;
};
/**
* Given a destination object and optionally many source objects,
* copy all properties from the source objects into the destination.
* The last source object given overrides properties from previous
* source objects.
* @param {Object} dest destination object
* @param {...Object} sources sources from which properties are pulled
* @returns {Object} dest
*/
exports.extend = function (dest) {
for (var i = 1; i < arguments.length; i++) {
var src = arguments[i];
for (var k in src) {
dest[k] = src[k];
}
}
return dest;
};
/**
* Extend a destination object with all properties of the src object,
* using defineProperty instead of simple assignment.
* @param {Object} dest
* @param {Object} src
* @returns {Object} dest
*/
exports.extendAll = function (dest, src) {
for (var i in src) {
Object.defineProperty(dest, i, Object.getOwnPropertyDescriptor(src, i));
}
return dest;
};
/**
* Extend a parent's prototype with all properties in a properties
* object.
*
* @param {Object} parent
* @param {Object} props
* @returns {Object}
*/
exports.inherit = function (parent, props) {
var parentProto = typeof parent === 'function' ? parent.prototype : parent,
proto = Object.create(parentProto);
exports.extendAll(proto, props);
return proto;
};
/**
* Given an object and a number of properties as strings, return version
* of that object with only those properties.
*
* @param {Object} src the object
* @param {Array<string>} properties an array of property names chosen
* to appear on the resulting object.
* @returns {Object} object with limited properties.
* @example
* var foo = { name: 'Charlie', age: 10 };
* var justName = pick(foo, ['name']);
* // justName = { name: 'Charlie' }
*/
exports.pick = function (src, properties) {
var result = {};
for (var i = 0; i < properties.length; i++) {
var k = properties[i];
if (k in src) {
result[k] = src[k];
}
}
return result;
};
var id = 1;
/**
* Return a unique numeric id, starting at 1 and incrementing with
* each call.
*
* @returns {Number} unique numeric id.
*/
exports.uniqueId = function () {
return id++;
};
/**
* Create a version of `fn` that only fires once every `time` millseconds.
*
* @param {Function} fn the function to be throttled
* @param {Number} time millseconds required between function calls
* @param {*} context the value of `this` with which the function is called
* @returns {Function} debounced function
*/
exports.throttle = function (fn, time, context) {
var lock, args, wrapperFn, later;
later = function () {
// reset lock and call if queued
lock = false;
if (args) {
wrapperFn.apply(context, args);
args = false;
}
};
wrapperFn = function () {
if (lock) {
// called too soon, queue to call later
args = arguments;
} else {
// call and lock until later
fn.apply(context, arguments);
setTimeout(later, time);
lock = true;
}
};
return wrapperFn;
};
/**
* Create a version of `fn` that is only called `time` milliseconds
* after its last invocation
*
* @param {Function} fn the function to be debounced
* @param {Number} time millseconds after which the function will be invoked
* @returns {Function} debounced function
*/
exports.debounce = function(fn, time) {
var timer, args;
return function() {
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(null, args);
}, time);
};
};
/**
* Given an array of member function names as strings, replace all of them
* with bound versions that will always refer to `context` as `this`. This
* is useful for classes where otherwise event bindings would reassign
* `this` to the evented object or some other value: this lets you ensure
* the `this` value always.
*
* @param {Array<string>} fns list of member function names
* @param {*} context the context value
* @returns {undefined} changes functions in-place
* @example
* function MyClass() {
* bindAll(['ontimer'], this);
* this.name = 'Tom';
* }
* MyClass.prototype.ontimer = function() {
* alert(this.name);
* };
* var myClass = new MyClass();
* setTimeout(myClass.ontimer, 100);
*/
exports.bindAll = function(fns, context) {
fns.forEach(function(fn) {
context[fn] = context[fn].bind(context);
});
};
/**
* Set the 'options' property on `obj` with properties
* from the `options` argument. Properties in the `options`
* object will override existing properties.
*
* @param {Object} obj destination object
* @param {Object} options object of override options
* @returns {Object} derived options object.
*/
exports.setOptions = function(obj, options) {
if (!obj.hasOwnProperty('options')) {
obj.options = obj.options ? Object.create(obj.options) : {};
}
for (var i in options) {
obj.options[i] = options[i];
}
return obj.options;
};
},{"unitbezier":116}],97:[function(require,module,exports){
// (c) Dean McNamee <dean@gmail.com>, 2012.
//
// https://github.com/deanm/css-color-parser-js
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// http://www.w3.org/TR/css3-color/
var kCSSColorTable = {
"transparent": [0,0,0,0], "aliceblue": [240,248,255,1],
"antiquewhite": [250,235,215,1], "aqua": [0,255,255,1],
"aquamarine": [127,255,212,1], "azure": [240,255,255,1],
"beige": [245,245,220,1], "bisque": [255,228,196,1],
"black": [0,0,0,1], "blanchedalmond": [255,235,205,1],
"blue": [0,0,255,1], "blueviolet": [138,43,226,1],
"brown": [165,42,42,1], "burlywood": [222,184,135,1],
"cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1],
"chocolate": [210,105,30,1], "coral": [255,127,80,1],
"cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1],
"crimson": [220,20,60,1], "cyan": [0,255,255,1],
"darkblue": [0,0,139,1], "darkcyan": [0,139,139,1],
"darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1],
"darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1],
"darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1],
"darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1],
"darkorchid": [153,50,204,1], "darkred": [139,0,0,1],
"darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1],
"darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1],
"darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1],
"darkviolet": [148,0,211,1], "deeppink": [255,20,147,1],
"deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1],
"dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1],
"firebrick": [178,34,34,1], "floralwhite": [255,250,240,1],
"forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1],
"gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1],
"gold": [255,215,0,1], "goldenrod": [218,165,32,1],
"gray": [128,128,128,1], "green": [0,128,0,1],
"greenyellow": [173,255,47,1], "grey": [128,128,128,1],
"honeydew": [240,255,240,1], "hotpink": [255,105,180,1],
"indianred": [205,92,92,1], "indigo": [75,0,130,1],
"ivory": [255,255,240,1], "khaki": [240,230,140,1],
"lavender": [230,230,250,1], "lavenderblush": [255,240,245,1],
"lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1],
"lightblue": [173,216,230,1], "lightcoral": [240,128,128,1],
"lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1],
"lightgray": [211,211,211,1], "lightgreen": [144,238,144,1],
"lightgrey": [211,211,211,1], "lightpink": [255,182,193,1],
"lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1],
"lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1],
"lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1],
"lightyellow": [255,255,224,1], "lime": [0,255,0,1],
"limegreen": [50,205,50,1], "linen": [250,240,230,1],
"magenta": [255,0,255,1], "maroon": [128,0,0,1],
"mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1],
"mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1],
"mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1],
"mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1],
"mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1],
"mintcream": [245,255,250,1], "mistyrose": [255,228,225,1],
"moccasin": [255,228,181,1], "navajowhite": [255,222,173,1],
"navy": [0,0,128,1], "oldlace": [253,245,230,1],
"olive": [128,128,0,1], "olivedrab": [107,142,35,1],
"orange": [255,165,0,1], "orangered": [255,69,0,1],
"orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1],
"palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1],
"palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1],
"peachpuff": [255,218,185,1], "peru": [205,133,63,1],
"pink": [255,192,203,1], "plum": [221,160,221,1],
"powderblue": [176,224,230,1], "purple": [128,0,128,1],
"red": [255,0,0,1], "rosybrown": [188,143,143,1],
"royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1],
"salmon": [250,128,114,1], "sandybrown": [244,164,96,1],
"seagreen": [46,139,87,1], "seashell": [255,245,238,1],
"sienna": [160,82,45,1], "silver": [192,192,192,1],
"skyblue": [135,206,235,1], "slateblue": [106,90,205,1],
"slategray": [112,128,144,1], "slategrey": [112,128,144,1],
"snow": [255,250,250,1], "springgreen": [0,255,127,1],
"steelblue": [70,130,180,1], "tan": [210,180,140,1],
"teal": [0,128,128,1], "thistle": [216,191,216,1],
"tomato": [255,99,71,1], "turquoise": [64,224,208,1],
"violet": [238,130,238,1], "wheat": [245,222,179,1],
"white": [255,255,255,1], "whitesmoke": [245,245,245,1],
"yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]}
function clamp_css_byte(i) { // Clamp to integer 0 .. 255.
i = Math.round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.
return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) { // int or percentage.
if (str[str.length - 1] === '%')
return clamp_css_byte(parseFloat(str) / 100 * 255);
return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) { // float or percentage.
if (str[str.length - 1] === '%')
return clamp_css_float(parseFloat(str) / 100);
return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
if (h < 0) h += 1;
else if (h > 1) h -= 1;
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
return m1;
}
function parseCSSColor(css_str) {
// Remove all whitespace, not compliant, but should just be more accepting.
var str = css_str.replace(/ /g, '').toLowerCase();
// Color keywords (and transparent) lookup.
if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup.
// #abc and #abc123 syntax.
if (str[0] === '#') {
if (str.length === 4) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN.
return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
(iv & 0xf0) | ((iv & 0xf0) >> 4),
(iv & 0xf) | ((iv & 0xf) << 4),
1];
} else if (str.length === 7) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN.
return [(iv & 0xff0000) >> 16,
(iv & 0xff00) >> 8,
iv & 0xff,
1];
}
return null;
}
var op = str.indexOf('('), ep = str.indexOf(')');
if (op !== -1 && ep + 1 === str.length) {
var fname = str.substr(0, op);
var params = str.substr(op+1, ep-(op+1)).split(',');
var alpha = 1; // To allow case fallthrough.
switch (fname) {
case 'rgba':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'rgb':
if (params.length !== 3) return null;
return [parse_css_int(params[0]),
parse_css_int(params[1]),
parse_css_int(params[2]),
alpha];
case 'hsla':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'hsl':
if (params.length !== 3) return null;
var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1
// NOTE(deanm): According to the CSS spec s/l should only be
// percentages, but we don't bother and let float or percentage.
var s = parse_css_float(params[1]);
var l = parse_css_float(params[2]);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),
alpha];
default:
return null;
}
}
return null;
}
try { exports.parseCSSColor = parseCSSColor } catch(e) { }
},{}],98:[function(require,module,exports){
'use strict';
var VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
function infix(operator) {
return function(_, key, value) {
if (key === '$type') {
return 't' + operator + VectorTileFeatureTypes.indexOf(value);
} else {
return 'p[' + JSON.stringify(key) + ']' + operator + JSON.stringify(value);
}
};
}
function strictInfix(operator) {
var nonstrictInfix = infix(operator);
return function(_, key, value) {
if (key === '$type') {
return nonstrictInfix(_, key, value);
} else {
return 'typeof(p[' + JSON.stringify(key) + ']) === typeof(' + JSON.stringify(value) + ') && ' +
nonstrictInfix(_, key, value);
}
};
}
var operators = {
'==': infix('==='),
'!=': infix('!=='),
'>': strictInfix('>'),
'<': strictInfix('<'),
'<=': strictInfix('<='),
'>=': strictInfix('>='),
'in': function(_, key) {
return Array.prototype.slice.call(arguments, 2).map(function(value) {
return '(' + operators['=='](_, key, value) + ')';
}).join('||') || 'false';
},
'!in': function() {
return '!(' + operators.in.apply(this, arguments) + ')';
},
'any': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('||') || 'false';
},
'all': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('&&') || 'true';
},
'none': function() {
return '!(' + operators.any.apply(this, arguments) + ')';
}
};
function compile(filter) {
return operators[filter[0]].apply(filter, filter);
}
function truth() {
return true;
}
/**
* Given a filter expressed as nested arrays, return a new function
* that evaluates whether a given feature (with a .properties or .tags property)
* passes its test.
*
* @param {Array} filter mapbox gl filter
* @returns {Function} filter-evaluating function
*/
module.exports = function (filter) {
if (!filter) return truth;
var filterStr = 'var p = f.properties || f.tags || {}, t = f.type; return ' + compile(filter) + ';';
// jshint evil: true
return new Function('f', filterStr);
};
},{}],99:[function(require,module,exports){
'use strict';
module.exports = clip;
/* clip features between two axis-parallel lines:
* | |
* ___|___ | /
* / | \____|____/
* | |
*/
function clip(features, scale, k1, k2, axis, intersect) {
k1 /= scale;
k2 /= scale;
var clipped = [];
for (var i = 0; i < features.length; i++) {
var feature = features[i],
geometry = feature.geometry,
type = feature.type,
min, max;
if (feature.min) {
min = feature.min[axis];
max = feature.max[axis];
if (min >= k1 && max <= k2) { // trivial accept
clipped.push(feature);
continue;
} else if (min > k2 || max < k1) continue; // trivial reject
}
var slices = type === 1 ?
clipPoints(geometry, k1, k2, axis) :
clipGeometry(geometry, k1, k2, axis, intersect, type === 3);
if (slices.length) {
// if a feature got clipped, it will likely get clipped on the next zoom level as well,
// so there's no need to recalculate bboxes
clipped.push({
geometry: slices,
type: type,
tags: features[i].tags || null
});
}
}
return clipped.length ? clipped : null;
}
function clipPoints(geometry, k1, k2, axis) {
var slice = [];
for (var i = 0; i < geometry.length; i++) {
var a = geometry[i],
ak = a[axis];
if (ak >= k1 && ak <= k2) slice.push(a);
}
return slice;
}
function clipGeometry(geometry, k1, k2, axis, intersect, closed) {
var slices = [];
for (var i = 0; i < geometry.length; i++) {
var ak = 0,
bk = 0,
b = null,
points = geometry[i],
area = points.area,
dist = points.dist,
len = points.length,
a, j;
var slice = [];
for (j = 0; j < len - 1; j++) {
a = b || points[j];
b = points[j + 1];
ak = bk || a[axis];
bk = b[axis];
if (ak < k1) {
if ((bk > k2)) { // ---|-----|-->
slice.push(intersect(a, b, k1), intersect(a, b, k2));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk >= k1) slice.push(intersect(a, b, k1)); // ---|--> |
} else if (ak > k2) {
if ((bk < k1)) { // <--|-----|---
slice.push(intersect(a, b, k2), intersect(a, b, k1));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk <= k2) slice.push(intersect(a, b, k2)); // | <--|---
} else {
slice.push(a);
if (bk < k1) { // <--|--- |
slice.push(intersect(a, b, k1));
if (!closed) slice = newSlice(slices, slice, area, dist);
} else if (bk > k2) { // | ---|-->
slice.push(intersect(a, b, k2));
if (!closed) slice = newSlice(slices, slice, area, dist);
}
// | --> |
}
}
// add the last point
a = points[len - 1];
ak = a[axis];
if (ak >= k1 && ak <= k2) slice.push(a);
// close the polygon if its endpoints are not the same after clipping
if (closed && slice[0] !== slice[slice.length - 1]) slice.push(slice[0]);
// add the final slice
newSlice(slices, slice, area, dist);
}
return slices;
}
function newSlice(slices, slice, area, dist) {
if (slice.length) {
// we don't recalculate the area/length of the unclipped geometry because the case where it goes
// below the visibility threshold as a result of clipping is rare, so we avoid doing unnecessary work
slice.area = area;
slice.dist = dist;
slices.push(slice);
}
return [];
}
},{}],100:[function(require,module,exports){
'use strict';
module.exports = convert;
var simplify = require('./simplify');
// converts GeoJSON feature into an intermediate projected JSON vector format with simplification data
function convert(data, tolerance) {
var features = [];
if (data.type === 'FeatureCollection') {
for (var i = 0; i < data.features.length; i++) {
convertFeature(features, data.features[i], tolerance);
}
} else if (data.type === 'Feature') {
convertFeature(features, data, tolerance);
} else {
// single geometry or a geometry collection
convertFeature(features, {geometry: data}, tolerance);
}
return features;
}
function convertFeature(features, feature, tolerance) {
var geom = feature.geometry,
type = geom.type,
coords = geom.coordinates,
tags = feature.properties,
i, j, rings;
if (type === 'Point') {
features.push(create(tags, 1, [projectPoint(coords)]));
} else if (type === 'MultiPoint') {
features.push(create(tags, 1, project(coords)));
} else if (type === 'LineString') {
features.push(create(tags, 2, [project(coords, tolerance)]));
} else if (type === 'MultiLineString' || type === 'Polygon') {
rings = [];
for (i = 0; i < coords.length; i++) {
rings.push(project(coords[i], tolerance));
}
features.push(create(tags, type === 'Polygon' ? 3 : 2, rings));
} else if (type === 'MultiPolygon') {
rings = [];
for (i = 0; i < coords.length; i++) {
for (j = 0; j < coords[i].length; j++) {
rings.push(project(coords[i][j], tolerance));
}
}
features.push(create(tags, 3, rings));
} else if (type === 'GeometryCollection') {
for (i = 0; i < geom.geometries.length; i++) {
convertFeature(features, {
geometry: geom.geometries[i],
properties: tags
}, tolerance);
}
} else {
console.warn('Unsupported GeoJSON type: ' + geom.type);
}
}
function create(tags, type, geometry) {
var feature = {
geometry: geometry,
type: type,
tags: tags || null,
min: [1, 1], // initial bbox values;
max: [0, 0] // note that all coords are in [0..1] range
};
calcBBox(feature);
return feature;
}
function project(lonlats, tolerance) {
var projected = [];
for (var i = 0; i < lonlats.length; i++) {
projected.push(projectPoint(lonlats[i]));
}
if (tolerance) {
simplify(projected, tolerance);
calcSize(projected);
}
return projected;
}
function projectPoint(p) {
var sin = Math.sin(p[1] * Math.PI / 180),
x = (p[0] / 360 + 0.5),
y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
return [x, y, 0];
}
// calculate area and length of the poly
function calcSize(points) {
var area = 0,
dist = 0;
for (var i = 0, a, b; i < points.length - 1; i++) {
a = b || points[i];
b = points[i + 1];
area += a[0] * b[1] - b[0] * a[1];
// use Manhattan distance instead of Euclidian one to avoid expensive square root computation
dist += Math.abs(b[0] - a[0]) + Math.abs(b[1] - a[1]);
}
points.area = Math.abs(area / 2);
points.dist = dist;
}
// calculate the feature bounding box for faster clipping later
function calcBBox(feature) {
var geometry = feature.geometry,
min = feature.min,
max = feature.max;
if (feature.type === 1) calcRingBBox(min, max, geometry);
else for (var i = 0; i < geometry.length; i++) calcRingBBox(min, max, geometry[i]);
return feature;
}
function calcRingBBox(min, max, points) {
for (var i = 0, p; i < points.length; i++) {
p = points[i];
min[0] = Math.min(p[0], min[0]);
max[0] = Math.max(p[0], max[0]);
min[1] = Math.min(p[1], min[1]);
max[1] = Math.max(p[1], max[1]);
}
}
},{"./simplify":102}],101:[function(require,module,exports){
'use strict';
module.exports = geojsonvt;
var convert = require('./convert'), // GeoJSON conversion and preprocessing
clip = require('./clip'), // stripe clipping algorithm
createTile = require('./tile'); // final simplified tile generation
function geojsonvt(data, options) {
return new GeoJSONVT(data, options);
}
function GeoJSONVT(data, options) {
options = this.options = extend(Object.create(this.options), options);
var debug = options.debug;
if (debug) console.time('preprocess data');
var z2 = 1 << options.baseZoom, // 2^z
features = convert(data, options.tolerance / (z2 * options.extent));
this.tiles = {};
if (debug) {
console.timeEnd('preprocess data');
console.time('generate tiles up to z' + options.maxZoom);
this.stats = {};
this.total = 0;
}
// start slicing from the top tile down
this.splitTile(features, 0, 0, 0);
if (debug) {
console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints);
console.timeEnd('generate tiles up to z' + options.maxZoom);
console.log('tiles generated:', this.total, JSON.stringify(this.stats));
}
}
GeoJSONVT.prototype.options = {
baseZoom: 14, // max zoom to preserve detail on
maxZoom: 4, // zoom to slice down to on first pass
maxPoints: 100, // stop slicing a tile below this number of points
tolerance: 3, // simplification tolerance (higher means simpler)
extent: 4096, // tile extent
buffer: 64, // tile buffer on each side
debug: 0 // logging level (0, 1 or 2)
};
GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) {
var stack = [features, z, x, y],
options = this.options,
debug = options.debug,
extent = options.extent,
buffer = options.buffer;
// avoid recursion by using a processing queue
while (stack.length) {
features = stack.shift();
z = stack.shift();
x = stack.shift();
y = stack.shift();
var z2 = 1 << z,
id = toID(z, x, y),
tile = this.tiles[id],
tileTolerance = z === options.baseZoom ? 0 : options.tolerance / (z2 * extent);
if (!tile) {
if (debug > 1) console.time('creation');
tile = this.tiles[id] = createTile(features, z2, x, y, tileTolerance, extent, z === options.baseZoom);
if (debug) {
if (debug > 1) {
console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)',
z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified);
console.timeEnd('creation');
}
var key = 'z' + z + ':';
this.stats[key] = (this.stats[key] || 0) + 1;
this.total++;
}
}
if (!cz && (z === options.maxZoom || tile.numPoints <= options.maxPoints ||
isClippedSquare(tile.features, extent, buffer)) || z === options.baseZoom || z === cz) {
tile.source = features;
continue; // stop tiling
}
if (cz) tile.source = features;
else tile.source = null;
if (debug > 1) console.time('clipping');
// values we'll use for clipping
var k1 = 0.5 * buffer / extent,
k2 = 0.5 - k1,
k3 = 0.5 + k1,
k4 = 1 + k1,
tl, bl, tr, br, left, right,
m, goLeft, goTop;
if (cz) { // if we have a specific tile to drill down to, calculate where to go
m = 1 << (cz - z);
goLeft = cx / m - x < 0.5;
goTop = cy / m - y < 0.5;
}
tl = bl = tr = br = left = right = null;
if (!cz || goLeft) left = clip(features, z2, x - k1, x + k3, 0, intersectX);
if (!cz || !goLeft) right = clip(features, z2, x + k2, x + k4, 0, intersectX);
if (left) {
if (!cz || goTop) tl = clip(left, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) bl = clip(left, z2, y + k2, y + k4, 1, intersectY);
}
if (right) {
if (!cz || goTop) tr = clip(right, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) br = clip(right, z2, y + k2, y + k4, 1, intersectY);
}
if (debug > 1) console.timeEnd('clipping');
if (tl) stack.push(tl, z + 1, x * 2, y * 2);
if (bl) stack.push(bl, z + 1, x * 2, y * 2 + 1);
if (tr) stack.push(tr, z + 1, x * 2 + 1, y * 2);
if (br) stack.push(br, z + 1, x * 2 + 1, y * 2 + 1);
}
};
GeoJSONVT.prototype.getTile = function (z, x, y) {
var id = toID(z, x, y);
if (this.tiles[id]) return this.tiles[id];
var options = this.options,
debug = options.debug;
if (debug > 1) console.log('drilling down to z%d-%d-%d', z, x, y);
var z0 = z,
x0 = x,
y0 = y,
parent;
while (!parent && z0 > 0) {
z0--;
x0 = Math.floor(x0 / 2);
y0 = Math.floor(y0 / 2);
parent = this.tiles[toID(z0, x0, y0)];
}
if (debug > 1) console.log('found parent tile z%d-%d-%d', z0, x0, y0);
// if we found a parent tile containing the original geometry, we can drill down from it
if (parent.source) {
if (isClippedSquare(parent.features, options.extent, options.buffer)) return parent;
if (debug) console.time('drilling down');
this.splitTile(parent.source, z0, x0, y0, z, x, y);
if (debug) console.timeEnd('drilling down');
}
return this.tiles[id];
};
// checks whether a tile is a whole-area fill after clipping; if it is, there's no sense slicing it further
function isClippedSquare(features, extent, buffer) {
if (features.length !== 1) return false;
var feature = features[0];
if (feature.type !== 3 || feature.geometry.length > 1) return false;
for (var i = 0; i < feature.geometry[0].length; i++) {
var p = feature.geometry[0][i];
if ((p[0] !== -buffer && p[0] !== extent + buffer) ||
(p[1] !== -buffer && p[1] !== extent + buffer)) return false;
}
return true;
}
function toID(z, x, y) {
return (((1 << z) * y + x) * 32) + z;
}
function intersectX(a, b, x) {
return [x, (x - a[0]) * (b[1] - a[1]) / (b[0] - a[0]) + a[1], 1];
}
function intersectY(a, b, y) {
return [(y - a[1]) * (b[0] - a[0]) / (b[1] - a[1]) + a[0], y, 1];
}
function extend(dest, src) {
for (var i in src) dest[i] = src[i];
return dest;
}
},{"./clip":99,"./convert":100,"./tile":103}],102:[function(require,module,exports){
'use strict';
module.exports = simplify;
// calculate simplification data using optimized Douglas-Peucker algorithm
function simplify(points, tolerance) {
var sqTolerance = tolerance * tolerance,
len = points.length,
first = 0,
last = len - 1,
stack = [],
i, maxSqDist, sqDist, index;
// always retain the endpoints (1 is the max value)
points[first][2] = 1;
points[last][2] = 1;
// avoid recursion by using a stack
while (last) {
maxSqDist = 0;
for (i = first + 1; i < last; i++) {
sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate
stack.push(first, index, index, last);
}
last = stack.pop();
first = stack.pop();
}
}
// square distance from a point to a segment
function getSqSegDist(p, a, b) {
var x = a[0], y = a[1],
bx = b[0], by = b[1],
px = p[0], py = p[1],
dx = bx - x,
dy = by - y;
if (dx !== 0 || dy !== 0) {
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = bx;
y = by;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = px - x;
dy = py - y;
return dx * dx + dy * dy;
}
},{}],103:[function(require,module,exports){
'use strict';
module.exports = createTile;
function createTile(features, z2, tx, ty, tolerance, extent, noSimplify) {
var tile = {
features: [],
numPoints: 0,
numSimplified: 0,
numFeatures: 0,
source: null
};
for (var i = 0; i < features.length; i++) {
tile.numFeatures++;
addFeature(tile, features[i], z2, tx, ty, tolerance, extent, noSimplify);
}
return tile;
}
function addFeature(tile, feature, z2, tx, ty, tolerance, extent, noSimplify) {
var geom = feature.geometry,
type = feature.type,
transformed = [],
sqTolerance = tolerance * tolerance,
i, j, ring, p;
if (type === 1) {
for (i = 0; i < geom.length; i++) {
transformed.push(transformPoint(geom[i], z2, tx, ty, extent));
tile.numPoints++;
tile.numSimplified++;
}
} else {
// simplify and transform projected coordinates for tile geometry
for (i = 0; i < geom.length; i++) {
ring = geom[i];
// filter out tiny polylines & polygons
if (!noSimplify && ((type === 2 && ring.dist < tolerance) ||
(type === 3 && ring.area < sqTolerance))) {
tile.numPoints += ring.length;
continue;
}
var transformedRing = [];
for (j = 0; j < ring.length; j++) {
p = ring[j];
// keep points with importance > tolerance
if (noSimplify || p[2] > sqTolerance) {
transformedRing.push(transformPoint(p, z2, tx, ty, extent));
tile.numSimplified++;
}
tile.numPoints++;
}
transformed.push(transformedRing);
}
}
if (transformed.length) {
tile.features.push({
geometry: transformed,
type: type,
tags: feature.tags || null
});
}
}
function transformPoint(p, z2, tx, ty, extent) {
var x = Math.round(extent * (p[0] * z2 - tx)),
y = Math.round(extent * (p[1] * z2 - ty));
return [x, y];
}
},{}],104:[function(require,module,exports){
/**
* @fileoverview gl-matrix - High performance matrix and vector operations
* @author Brandon Jones
* @author Colin MacKenzie IV
* @version 2.2.1
*/
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
(function(_global) {
"use strict";
var shim = {};
if (typeof(exports) === 'undefined') {
if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
shim.exports = {};
define(function() {
return shim.exports;
});
} else {
// gl-matrix lives in a browser, define its namespaces in global
shim.exports = typeof(window) !== 'undefined' ? window : _global;
}
}
else {
// gl-matrix lives in commonjs, define its namespaces in exports
shim.exports = exports;
}
(function(exports) {
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
if(!GLMAT_EPSILON) {
var GLMAT_EPSILON = 0.000001;
}
if(!GLMAT_ARRAY_TYPE) {
var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
}
if(!GLMAT_RANDOM) {
var GLMAT_RANDOM = Math.random;
}
/**
* @class Common utilities
* @name glMatrix
*/
var glMatrix = {};
/**
* Sets the type of array used when creating new vectors and matricies
*
* @param {Type} type Array type, such as Float32Array or Array
*/
glMatrix.setMatrixArrayType = function(type) {
GLMAT_ARRAY_TYPE = type;
}
if(typeof(exports) !== 'undefined') {
exports.glMatrix = glMatrix;
}
var degree = Math.PI / 180;
/**
* Convert Degree To Radian
*
* @param {Number} Angle in Degrees
*/
glMatrix.toRadian = function(a){
return a * degree;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2 Dimensional Vector
* @name vec2
*/
var vec2 = {};
/**
* Creates a new, empty vec2
*
* @returns {vec2} a new 2D vector
*/
vec2.create = function() {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = 0;
out[1] = 0;
return out;
};
/**
* Creates a new vec2 initialized with values from an existing vector
*
* @param {vec2} a vector to clone
* @returns {vec2} a new 2D vector
*/
vec2.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = a[0];
out[1] = a[1];
return out;
};
/**
* Creates a new vec2 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} a new 2D vector
*/
vec2.fromValues = function(x, y) {
var out = new GLMAT_ARRAY_TYPE(2);
out[0] = x;
out[1] = y;
return out;
};
/**
* Copy the values from one vec2 to another
*
* @param {vec2} out the receiving vector
* @param {vec2} a the source vector
* @returns {vec2} out
*/
vec2.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
return out;
};
/**
* Set the components of a vec2 to the given values
*
* @param {vec2} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} out
*/
vec2.set = function(out, x, y) {
out[0] = x;
out[1] = y;
return out;
};
/**
* Adds two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
return out;
};
/**
* Alias for {@link vec2.subtract}
* @function
*/
vec2.sub = vec2.subtract;
/**
* Multiplies two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
return out;
};
/**
* Alias for {@link vec2.multiply}
* @function
*/
vec2.mul = vec2.multiply;
/**
* Divides two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
return out;
};
/**
* Alias for {@link vec2.divide}
* @function
*/
vec2.div = vec2.divide;
/**
* Returns the minimum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
return out;
};
/**
* Returns the maximum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
vec2.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
return out;
};
/**
* Scales a vec2 by a scalar number
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec2} out
*/
vec2.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
return out;
};
/**
* Adds two vec2's after scaling the second operand by a scalar value
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec2} out
*/
vec2.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} distance between a and b
*/
vec2.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return Math.sqrt(x*x + y*y);
};
/**
* Alias for {@link vec2.distance}
* @function
*/
vec2.dist = vec2.distance;
/**
* Calculates the squared euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} squared distance between a and b
*/
vec2.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return x*x + y*y;
};
/**
* Alias for {@link vec2.squaredDistance}
* @function
*/
vec2.sqrDist = vec2.squaredDistance;
/**
* Calculates the length of a vec2
*
* @param {vec2} a vector to calculate length of
* @returns {Number} length of a
*/
vec2.length = function (a) {
var x = a[0],
y = a[1];
return Math.sqrt(x*x + y*y);
};
/**
* Alias for {@link vec2.length}
* @function
*/
vec2.len = vec2.length;
/**
* Calculates the squared length of a vec2
*
* @param {vec2} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec2.squaredLength = function (a) {
var x = a[0],
y = a[1];
return x*x + y*y;
};
/**
* Alias for {@link vec2.squaredLength}
* @function
*/
vec2.sqrLen = vec2.squaredLength;
/**
* Negates the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to negate
* @returns {vec2} out
*/
vec2.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
return out;
};
/**
* Normalize a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to normalize
* @returns {vec2} out
*/
vec2.normalize = function(out, a) {
var x = a[0],
y = a[1];
var len = x*x + y*y;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
}
return out;
};
/**
* Calculates the dot product of two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} dot product of a and b
*/
vec2.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1];
};
/**
* Computes the cross product of two vec2's
* Note that the cross product must by definition produce a 3D vector
*
* @param {vec3} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec3} out
*/
vec2.cross = function(out, a, b) {
var z = a[0] * b[1] - a[1] * b[0];
out[0] = out[1] = 0;
out[2] = z;
return out;
};
/**
* Performs a linear interpolation between two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec2} out
*/
vec2.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec2} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec2} out
*/
vec2.random = function (out, scale) {
scale = scale || 1.0;
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
out[0] = Math.cos(r) * scale;
out[1] = Math.sin(r) * scale;
return out;
};
/**
* Transforms the vec2 with a mat2
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat2 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y;
out[1] = m[1] * x + m[3] * y;
return out;
};
/**
* Transforms the vec2 with a mat2d
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2d} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat2d = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y + m[4];
out[1] = m[1] * x + m[3] * y + m[5];
return out;
};
/**
* Transforms the vec2 with a mat3
* 3rd vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat3} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat3 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[3] * y + m[6];
out[1] = m[1] * x + m[4] * y + m[7];
return out;
};
/**
* Transforms the vec2 with a mat4
* 3rd vector component is implicitly '0'
* 4th vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec2} out
*/
vec2.transformMat4 = function(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[4] * y + m[12];
out[1] = m[1] * x + m[5] * y + m[13];
return out;
};
/**
* Perform some operation over an array of vec2s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec2.forEach = (function() {
var vec = vec2.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 2;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec2} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec2.str = function (a) {
return 'vec2(' + a[0] + ', ' + a[1] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec2 = vec2;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 3 Dimensional Vector
* @name vec3
*/
var vec3 = {};
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
vec3.create = function() {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = 0;
out[1] = 0;
out[2] = 0;
return out;
};
/**
* Creates a new vec3 initialized with values from an existing vector
*
* @param {vec3} a vector to clone
* @returns {vec3} a new 3D vector
*/
vec3.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
};
/**
* Creates a new vec3 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} a new 3D vector
*/
vec3.fromValues = function(x, y, z) {
var out = new GLMAT_ARRAY_TYPE(3);
out[0] = x;
out[1] = y;
out[2] = z;
return out;
};
/**
* Copy the values from one vec3 to another
*
* @param {vec3} out the receiving vector
* @param {vec3} a the source vector
* @returns {vec3} out
*/
vec3.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
};
/**
* Set the components of a vec3 to the given values
*
* @param {vec3} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} out
*/
vec3.set = function(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
return out;
};
/**
* Adds two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
return out;
};
/**
* Alias for {@link vec3.subtract}
* @function
*/
vec3.sub = vec3.subtract;
/**
* Multiplies two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
return out;
};
/**
* Alias for {@link vec3.multiply}
* @function
*/
vec3.mul = vec3.multiply;
/**
* Divides two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
return out;
};
/**
* Alias for {@link vec3.divide}
* @function
*/
vec3.div = vec3.divide;
/**
* Returns the minimum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
return out;
};
/**
* Returns the maximum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
return out;
};
/**
* Scales a vec3 by a scalar number
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec3} out
*/
vec3.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
return out;
};
/**
* Adds two vec3's after scaling the second operand by a scalar value
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec3} out
*/
vec3.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} distance between a and b
*/
vec3.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2];
return Math.sqrt(x*x + y*y + z*z);
};
/**
* Alias for {@link vec3.distance}
* @function
*/
vec3.dist = vec3.distance;
/**
* Calculates the squared euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} squared distance between a and b
*/
vec3.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2];
return x*x + y*y + z*z;
};
/**
* Alias for {@link vec3.squaredDistance}
* @function
*/
vec3.sqrDist = vec3.squaredDistance;
/**
* Calculates the length of a vec3
*
* @param {vec3} a vector to calculate length of
* @returns {Number} length of a
*/
vec3.length = function (a) {
var x = a[0],
y = a[1],
z = a[2];
return Math.sqrt(x*x + y*y + z*z);
};
/**
* Alias for {@link vec3.length}
* @function
*/
vec3.len = vec3.length;
/**
* Calculates the squared length of a vec3
*
* @param {vec3} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec3.squaredLength = function (a) {
var x = a[0],
y = a[1],
z = a[2];
return x*x + y*y + z*z;
};
/**
* Alias for {@link vec3.squaredLength}
* @function
*/
vec3.sqrLen = vec3.squaredLength;
/**
* Negates the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to negate
* @returns {vec3} out
*/
vec3.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
return out;
};
/**
* Normalize a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to normalize
* @returns {vec3} out
*/
vec3.normalize = function(out, a) {
var x = a[0],
y = a[1],
z = a[2];
var len = x*x + y*y + z*z;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
out[2] = a[2] * len;
}
return out;
};
/**
* Calculates the dot product of two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} dot product of a and b
*/
vec3.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
};
/**
* Computes the cross product of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
vec3.cross = function(out, a, b) {
var ax = a[0], ay = a[1], az = a[2],
bx = b[0], by = b[1], bz = b[2];
out[0] = ay * bz - az * by;
out[1] = az * bx - ax * bz;
out[2] = ax * by - ay * bx;
return out;
};
/**
* Performs a linear interpolation between two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec3} out
*/
vec3.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1],
az = a[2];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec3} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec3} out
*/
vec3.random = function (out, scale) {
scale = scale || 1.0;
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
var z = (GLMAT_RANDOM() * 2.0) - 1.0;
var zScale = Math.sqrt(1.0-z*z) * scale;
out[0] = Math.cos(r) * zScale;
out[1] = Math.sin(r) * zScale;
out[2] = z * scale;
return out;
};
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec3} out
*/
vec3.transformMat4 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2];
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
return out;
};
/**
* Transforms the vec3 with a mat3.
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m the 3x3 matrix to transform with
* @returns {vec3} out
*/
vec3.transformMat3 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2];
out[0] = x * m[0] + y * m[3] + z * m[6];
out[1] = x * m[1] + y * m[4] + z * m[7];
out[2] = x * m[2] + y * m[5] + z * m[8];
return out;
};
/**
* Transforms the vec3 with a quat
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec3} out
*/
vec3.transformQuat = function(out, a, q) {
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
var x = a[0], y = a[1], z = a[2],
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
// calculate quat * vec
ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return out;
};
/*
* Rotate a 3D vector around the x-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateX = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0];
r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/*
* Rotate a 3D vector around the y-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateY = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
r[1] = p[1];
r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/*
* Rotate a 3D vector around the z-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
vec3.rotateZ = function(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
r[2] = p[2];
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
};
/**
* Perform some operation over an array of vec3s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec3.forEach = (function() {
var vec = vec3.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 3;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec3} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec3.str = function (a) {
return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec3 = vec3;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 4 Dimensional Vector
* @name vec4
*/
var vec4 = {};
/**
* Creates a new, empty vec4
*
* @returns {vec4} a new 4D vector
*/
vec4.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 0;
return out;
};
/**
* Creates a new vec4 initialized with values from an existing vector
*
* @param {vec4} a vector to clone
* @returns {vec4} a new 4D vector
*/
vec4.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Creates a new vec4 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} a new 4D vector
*/
vec4.fromValues = function(x, y, z, w) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
};
/**
* Copy the values from one vec4 to another
*
* @param {vec4} out the receiving vector
* @param {vec4} a the source vector
* @returns {vec4} out
*/
vec4.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Set the components of a vec4 to the given values
*
* @param {vec4} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} out
*/
vec4.set = function(out, x, y, z, w) {
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
};
/**
* Adds two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.add = function(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
return out;
};
/**
* Subtracts vector b from vector a
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.subtract = function(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
return out;
};
/**
* Alias for {@link vec4.subtract}
* @function
*/
vec4.sub = vec4.subtract;
/**
* Multiplies two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.multiply = function(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
out[3] = a[3] * b[3];
return out;
};
/**
* Alias for {@link vec4.multiply}
* @function
*/
vec4.mul = vec4.multiply;
/**
* Divides two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.divide = function(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
out[3] = a[3] / b[3];
return out;
};
/**
* Alias for {@link vec4.divide}
* @function
*/
vec4.div = vec4.divide;
/**
* Returns the minimum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.min = function(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
out[3] = Math.min(a[3], b[3]);
return out;
};
/**
* Returns the maximum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
vec4.max = function(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
out[3] = Math.max(a[3], b[3]);
return out;
};
/**
* Scales a vec4 by a scalar number
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec4} out
*/
vec4.scale = function(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
return out;
};
/**
* Adds two vec4's after scaling the second operand by a scalar value
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec4} out
*/
vec4.scaleAndAdd = function(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
return out;
};
/**
* Calculates the euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} distance between a and b
*/
vec4.distance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2],
w = b[3] - a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
};
/**
* Alias for {@link vec4.distance}
* @function
*/
vec4.dist = vec4.distance;
/**
* Calculates the squared euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} squared distance between a and b
*/
vec4.squaredDistance = function(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2],
w = b[3] - a[3];
return x*x + y*y + z*z + w*w;
};
/**
* Alias for {@link vec4.squaredDistance}
* @function
*/
vec4.sqrDist = vec4.squaredDistance;
/**
* Calculates the length of a vec4
*
* @param {vec4} a vector to calculate length of
* @returns {Number} length of a
*/
vec4.length = function (a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
};
/**
* Alias for {@link vec4.length}
* @function
*/
vec4.len = vec4.length;
/**
* Calculates the squared length of a vec4
*
* @param {vec4} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
vec4.squaredLength = function (a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
return x*x + y*y + z*z + w*w;
};
/**
* Alias for {@link vec4.squaredLength}
* @function
*/
vec4.sqrLen = vec4.squaredLength;
/**
* Negates the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to negate
* @returns {vec4} out
*/
vec4.negate = function(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = -a[3];
return out;
};
/**
* Normalize a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to normalize
* @returns {vec4} out
*/
vec4.normalize = function(out, a) {
var x = a[0],
y = a[1],
z = a[2],
w = a[3];
var len = x*x + y*y + z*z + w*w;
if (len > 0) {
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
out[2] = a[2] * len;
out[3] = a[3] * len;
}
return out;
};
/**
* Calculates the dot product of two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} dot product of a and b
*/
vec4.dot = function (a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
};
/**
* Performs a linear interpolation between two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec4} out
*/
vec4.lerp = function (out, a, b, t) {
var ax = a[0],
ay = a[1],
az = a[2],
aw = a[3];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
out[3] = aw + t * (b[3] - aw);
return out;
};
/**
* Generates a random vector with the given scale
*
* @param {vec4} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec4} out
*/
vec4.random = function (out, scale) {
scale = scale || 1.0;
//TODO: This is a pretty awful way of doing this. Find something better.
out[0] = GLMAT_RANDOM();
out[1] = GLMAT_RANDOM();
out[2] = GLMAT_RANDOM();
out[3] = GLMAT_RANDOM();
vec4.normalize(out, out);
vec4.scale(out, out, scale);
return out;
};
/**
* Transforms the vec4 with a mat4.
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec4} out
*/
vec4.transformMat4 = function(out, a, m) {
var x = a[0], y = a[1], z = a[2], w = a[3];
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
return out;
};
/**
* Transforms the vec4 with a quat
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec4} out
*/
vec4.transformQuat = function(out, a, q) {
var x = a[0], y = a[1], z = a[2],
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
// calculate quat * vec
ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return out;
};
/**
* Perform some operation over an array of vec4s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec4.forEach = (function() {
var vec = vec4.create();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 4;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
}
return a;
};
})();
/**
* Returns a string representation of a vector
*
* @param {vec4} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
vec4.str = function (a) {
return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.vec4 = vec4;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2x2 Matrix
* @name mat2
*/
var mat2 = {};
/**
* Creates a new identity mat2
*
* @returns {mat2} a new 2x2 matrix
*/
mat2.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Creates a new mat2 initialized with values from an existing matrix
*
* @param {mat2} a matrix to clone
* @returns {mat2} a new 2x2 matrix
*/
mat2.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Copy the values from one mat2 to another
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
};
/**
* Set a mat2 to the identity matrix
*
* @param {mat2} out the receiving matrix
* @returns {mat2} out
*/
mat2.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Transpose the values of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a1 = a[1];
out[1] = a[2];
out[2] = a1;
} else {
out[0] = a[0];
out[1] = a[2];
out[2] = a[1];
out[3] = a[3];
}
return out;
};
/**
* Inverts a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.invert = function(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
// Calculate the determinant
det = a0 * a3 - a2 * a1;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = a3 * det;
out[1] = -a1 * det;
out[2] = -a2 * det;
out[3] = a0 * det;
return out;
};
/**
* Calculates the adjugate of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
mat2.adjoint = function(out, a) {
// Caching this value is nessecary if out == a
var a0 = a[0];
out[0] = a[3];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a0;
return out;
};
/**
* Calculates the determinant of a mat2
*
* @param {mat2} a the source matrix
* @returns {Number} determinant of a
*/
mat2.determinant = function (a) {
return a[0] * a[3] - a[2] * a[1];
};
/**
* Multiplies two mat2's
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @returns {mat2} out
*/
mat2.multiply = function (out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
return out;
};
/**
* Alias for {@link mat2.multiply}
* @function
*/
mat2.mul = mat2.multiply;
/**
* Rotates a mat2 by the given angle
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2} out
*/
mat2.rotate = function (out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
return out;
};
/**
* Scales the mat2 by the dimensions in the given vec2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2} out
**/
mat2.scale = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
return out;
};
/**
* Returns a string representation of a mat2
*
* @param {mat2} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat2.str = function (a) {
return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
/**
* Returns Frobenius norm of a mat2
*
* @param {mat2} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat2.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
};
/**
* Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
* @param {mat2} L the lower triangular matrix
* @param {mat2} D the diagonal matrix
* @param {mat2} U the upper triangular matrix
* @param {mat2} a the input matrix to factorize
*/
mat2.LDU = function (L, D, U, a) {
L[2] = a[2]/a[0];
U[0] = a[0];
U[1] = a[1];
U[3] = a[3] - L[2] * U[1];
return [L, D, U];
};
if(typeof(exports) !== 'undefined') {
exports.mat2 = mat2;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 2x3 Matrix
* @name mat2d
*
* @description
* A mat2d contains six elements defined as:
* <pre>
* [a, c, tx,
* b, d, ty]
* </pre>
* This is a short form for the 3x3 matrix:
* <pre>
* [a, c, tx,
* b, d, ty,
* 0, 0, 1]
* </pre>
* The last row is ignored so the array is shorter and operations are faster.
*/
var mat2d = {};
/**
* Creates a new identity mat2d
*
* @returns {mat2d} a new 2x3 matrix
*/
mat2d.create = function() {
var out = new GLMAT_ARRAY_TYPE(6);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
};
/**
* Creates a new mat2d initialized with values from an existing matrix
*
* @param {mat2d} a matrix to clone
* @returns {mat2d} a new 2x3 matrix
*/
mat2d.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(6);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
};
/**
* Copy the values from one mat2d to another
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
mat2d.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
};
/**
* Set a mat2d to the identity matrix
*
* @param {mat2d} out the receiving matrix
* @returns {mat2d} out
*/
mat2d.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
};
/**
* Inverts a mat2d
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
mat2d.invert = function(out, a) {
var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
atx = a[4], aty = a[5];
var det = aa * ad - ab * ac;
if(!det){
return null;
}
det = 1.0 / det;
out[0] = ad * det;
out[1] = -ab * det;
out[2] = -ac * det;
out[3] = aa * det;
out[4] = (ac * aty - ad * atx) * det;
out[5] = (ab * atx - aa * aty) * det;
return out;
};
/**
* Calculates the determinant of a mat2d
*
* @param {mat2d} a the source matrix
* @returns {Number} determinant of a
*/
mat2d.determinant = function (a) {
return a[0] * a[3] - a[1] * a[2];
};
/**
* Multiplies two mat2d's
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @returns {mat2d} out
*/
mat2d.multiply = function (out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
out[4] = a0 * b4 + a2 * b5 + a4;
out[5] = a1 * b4 + a3 * b5 + a5;
return out;
};
/**
* Alias for {@link mat2d.multiply}
* @function
*/
mat2d.mul = mat2d.multiply;
/**
* Rotates a mat2d by the given angle
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2d} out
*/
mat2d.rotate = function (out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
out[4] = a4;
out[5] = a5;
return out;
};
/**
* Scales the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2d} out
**/
mat2d.scale = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
out[4] = a4;
out[5] = a5;
return out;
};
/**
* Translates the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to translate the matrix by
* @returns {mat2d} out
**/
mat2d.translate = function(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
v0 = v[0], v1 = v[1];
out[0] = a0;
out[1] = a1;
out[2] = a2;
out[3] = a3;
out[4] = a0 * v0 + a2 * v1 + a4;
out[5] = a1 * v0 + a3 * v1 + a5;
return out;
};
/**
* Returns a string representation of a mat2d
*
* @param {mat2d} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat2d.str = function (a) {
return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ')';
};
/**
* Returns Frobenius norm of a mat2d
*
* @param {mat2d} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat2d.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
};
if(typeof(exports) !== 'undefined') {
exports.mat2d = mat2d;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 3x3 Matrix
* @name mat3
*/
var mat3 = {};
/**
* Creates a new identity mat3
*
* @returns {mat3} a new 3x3 matrix
*/
mat3.create = function() {
var out = new GLMAT_ARRAY_TYPE(9);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
};
/**
* Copies the upper-left 3x3 values into the given mat3.
*
* @param {mat3} out the receiving 3x3 matrix
* @param {mat4} a the source 4x4 matrix
* @returns {mat3} out
*/
mat3.fromMat4 = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[4];
out[4] = a[5];
out[5] = a[6];
out[6] = a[8];
out[7] = a[9];
out[8] = a[10];
return out;
};
/**
* Creates a new mat3 initialized with values from an existing matrix
*
* @param {mat3} a matrix to clone
* @returns {mat3} a new 3x3 matrix
*/
mat3.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(9);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Copy the values from one mat3 to another
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Set a mat3 to the identity matrix
*
* @param {mat3} out the receiving matrix
* @returns {mat3} out
*/
mat3.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
};
/**
* Transpose the values of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a12 = a[5];
out[1] = a[3];
out[2] = a[6];
out[3] = a01;
out[5] = a[7];
out[6] = a02;
out[7] = a12;
} else {
out[0] = a[0];
out[1] = a[3];
out[2] = a[6];
out[3] = a[1];
out[4] = a[4];
out[5] = a[7];
out[6] = a[2];
out[7] = a[5];
out[8] = a[8];
}
return out;
};
/**
* Inverts a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.invert = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
b01 = a22 * a11 - a12 * a21,
b11 = -a22 * a10 + a12 * a20,
b21 = a21 * a10 - a11 * a20,
// Calculate the determinant
det = a00 * b01 + a01 * b11 + a02 * b21;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = b01 * det;
out[1] = (-a22 * a01 + a02 * a21) * det;
out[2] = (a12 * a01 - a02 * a11) * det;
out[3] = b11 * det;
out[4] = (a22 * a00 - a02 * a20) * det;
out[5] = (-a12 * a00 + a02 * a10) * det;
out[6] = b21 * det;
out[7] = (-a21 * a00 + a01 * a20) * det;
out[8] = (a11 * a00 - a01 * a10) * det;
return out;
};
/**
* Calculates the adjugate of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
mat3.adjoint = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8];
out[0] = (a11 * a22 - a12 * a21);
out[1] = (a02 * a21 - a01 * a22);
out[2] = (a01 * a12 - a02 * a11);
out[3] = (a12 * a20 - a10 * a22);
out[4] = (a00 * a22 - a02 * a20);
out[5] = (a02 * a10 - a00 * a12);
out[6] = (a10 * a21 - a11 * a20);
out[7] = (a01 * a20 - a00 * a21);
out[8] = (a00 * a11 - a01 * a10);
return out;
};
/**
* Calculates the determinant of a mat3
*
* @param {mat3} a the source matrix
* @returns {Number} determinant of a
*/
mat3.determinant = function (a) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8];
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
};
/**
* Multiplies two mat3's
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @returns {mat3} out
*/
mat3.multiply = function (out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
b00 = b[0], b01 = b[1], b02 = b[2],
b10 = b[3], b11 = b[4], b12 = b[5],
b20 = b[6], b21 = b[7], b22 = b[8];
out[0] = b00 * a00 + b01 * a10 + b02 * a20;
out[1] = b00 * a01 + b01 * a11 + b02 * a21;
out[2] = b00 * a02 + b01 * a12 + b02 * a22;
out[3] = b10 * a00 + b11 * a10 + b12 * a20;
out[4] = b10 * a01 + b11 * a11 + b12 * a21;
out[5] = b10 * a02 + b11 * a12 + b12 * a22;
out[6] = b20 * a00 + b21 * a10 + b22 * a20;
out[7] = b20 * a01 + b21 * a11 + b22 * a21;
out[8] = b20 * a02 + b21 * a12 + b22 * a22;
return out;
};
/**
* Alias for {@link mat3.multiply}
* @function
*/
mat3.mul = mat3.multiply;
/**
* Translate a mat3 by the given vector
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to translate
* @param {vec2} v vector to translate by
* @returns {mat3} out
*/
mat3.translate = function(out, a, v) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
x = v[0], y = v[1];
out[0] = a00;
out[1] = a01;
out[2] = a02;
out[3] = a10;
out[4] = a11;
out[5] = a12;
out[6] = x * a00 + y * a10 + a20;
out[7] = x * a01 + y * a11 + a21;
out[8] = x * a02 + y * a12 + a22;
return out;
};
/**
* Rotates a mat3 by the given angle
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat3} out
*/
mat3.rotate = function (out, a, rad) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = c * a00 + s * a10;
out[1] = c * a01 + s * a11;
out[2] = c * a02 + s * a12;
out[3] = c * a10 - s * a00;
out[4] = c * a11 - s * a01;
out[5] = c * a12 - s * a02;
out[6] = a20;
out[7] = a21;
out[8] = a22;
return out;
};
/**
* Scales the mat3 by the dimensions in the given vec2
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat3} out
**/
mat3.scale = function(out, a, v) {
var x = v[0], y = v[1];
out[0] = x * a[0];
out[1] = x * a[1];
out[2] = x * a[2];
out[3] = y * a[3];
out[4] = y * a[4];
out[5] = y * a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
};
/**
* Copies the values from a mat2d into a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat2d} a the matrix to copy
* @returns {mat3} out
**/
mat3.fromMat2d = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = 0;
out[3] = a[2];
out[4] = a[3];
out[5] = 0;
out[6] = a[4];
out[7] = a[5];
out[8] = 1;
return out;
};
/**
* Calculates a 3x3 matrix from the given quaternion
*
* @param {mat3} out mat3 receiving operation result
* @param {quat} q Quaternion to create matrix from
*
* @returns {mat3} out
*/
mat3.fromQuat = function (out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
yx = y * x2,
yy = y * y2,
zx = z * x2,
zy = z * y2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - yy - zz;
out[3] = yx - wz;
out[6] = zx + wy;
out[1] = yx + wz;
out[4] = 1 - xx - zz;
out[7] = zy - wx;
out[2] = zx - wy;
out[5] = zy + wx;
out[8] = 1 - xx - yy;
return out;
};
/**
* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
*
* @param {mat3} out mat3 receiving operation result
* @param {mat4} a Mat4 to derive the normal matrix from
*
* @returns {mat3} out
*/
mat3.normalFromMat4 = function (out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
// Calculate the determinant
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
return out;
};
/**
* Returns a string representation of a mat3
*
* @param {mat3} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat3.str = function (a) {
return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
a[6] + ', ' + a[7] + ', ' + a[8] + ')';
};
/**
* Returns Frobenius norm of a mat3
*
* @param {mat3} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat3.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
};
if(typeof(exports) !== 'undefined') {
exports.mat3 = mat3;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class 4x4 Matrix
* @name mat4
*/
var mat4 = {};
/**
* Creates a new identity mat4
*
* @returns {mat4} a new 4x4 matrix
*/
mat4.create = function() {
var out = new GLMAT_ARRAY_TYPE(16);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Creates a new mat4 initialized with values from an existing matrix
*
* @param {mat4} a matrix to clone
* @returns {mat4} a new 4x4 matrix
*/
mat4.clone = function(a) {
var out = new GLMAT_ARRAY_TYPE(16);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Copy the values from one mat4 to another
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.copy = function(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Set a mat4 to the identity matrix
*
* @param {mat4} out the receiving matrix
* @returns {mat4} out
*/
mat4.identity = function(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Transpose the values of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.transpose = function(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a03 = a[3],
a12 = a[6], a13 = a[7],
a23 = a[11];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a01;
out[6] = a[9];
out[7] = a[13];
out[8] = a02;
out[9] = a12;
out[11] = a[14];
out[12] = a03;
out[13] = a13;
out[14] = a23;
} else {
out[0] = a[0];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a[1];
out[5] = a[5];
out[6] = a[9];
out[7] = a[13];
out[8] = a[2];
out[9] = a[6];
out[10] = a[10];
out[11] = a[14];
out[12] = a[3];
out[13] = a[7];
out[14] = a[11];
out[15] = a[15];
}
return out;
};
/**
* Inverts a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.invert = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
// Calculate the determinant
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return out;
};
/**
* Calculates the adjugate of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
mat4.adjoint = function(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
return out;
};
/**
* Calculates the determinant of a mat4
*
* @param {mat4} a the source matrix
* @returns {Number} determinant of a
*/
mat4.determinant = function (a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32;
// Calculate the determinant
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
};
/**
* Multiplies two mat4's
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @returns {mat4} out
*/
mat4.multiply = function (out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
// Cache only the current line of the second matrix
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
return out;
};
/**
* Alias for {@link mat4.multiply}
* @function
*/
mat4.mul = mat4.multiply;
/**
* Translate a mat4 by the given vector
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to translate
* @param {vec3} v vector to translate by
* @returns {mat4} out
*/
mat4.translate = function (out, a, v) {
var x = v[0], y = v[1], z = v[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
};
/**
* Scales the mat4 by the dimensions in the given vec3
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to scale
* @param {vec3} v the vec3 to scale the matrix by
* @returns {mat4} out
**/
mat4.scale = function(out, a, v) {
var x = v[0], y = v[1], z = v[2];
out[0] = a[0] * x;
out[1] = a[1] * x;
out[2] = a[2] * x;
out[3] = a[3] * x;
out[4] = a[4] * y;
out[5] = a[5] * y;
out[6] = a[6] * y;
out[7] = a[7] * y;
out[8] = a[8] * z;
out[9] = a[9] * z;
out[10] = a[10] * z;
out[11] = a[11] * z;
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
};
/**
* Rotates a mat4 by the given angle
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @param {vec3} axis the axis to rotate around
* @returns {mat4} out
*/
mat4.rotate = function (out, a, rad, axis) {
var x = axis[0], y = axis[1], z = axis[2],
len = Math.sqrt(x * x + y * y + z * z),
s, c, t,
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23,
b00, b01, b02,
b10, b11, b12,
b20, b21, b22;
if (Math.abs(len) < GLMAT_EPSILON) { return null; }
len = 1 / len;
x *= len;
y *= len;
z *= len;
s = Math.sin(rad);
c = Math.cos(rad);
t = 1 - c;
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
// Construct the elements of the rotation matrix
b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
// Perform rotation-specific matrix multiplication
out[0] = a00 * b00 + a10 * b01 + a20 * b02;
out[1] = a01 * b00 + a11 * b01 + a21 * b02;
out[2] = a02 * b00 + a12 * b01 + a22 * b02;
out[3] = a03 * b00 + a13 * b01 + a23 * b02;
out[4] = a00 * b10 + a10 * b11 + a20 * b12;
out[5] = a01 * b10 + a11 * b11 + a21 * b12;
out[6] = a02 * b10 + a12 * b11 + a22 * b12;
out[7] = a03 * b10 + a13 * b11 + a23 * b12;
out[8] = a00 * b20 + a10 * b21 + a20 * b22;
out[9] = a01 * b20 + a11 * b21 + a21 * b22;
out[10] = a02 * b20 + a12 * b21 + a22 * b22;
out[11] = a03 * b20 + a13 * b21 + a23 * b22;
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
return out;
};
/**
* Rotates a matrix by the given angle around the X axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateX = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a10 = a[4],
a11 = a[5],
a12 = a[6],
a13 = a[7],
a20 = a[8],
a21 = a[9],
a22 = a[10],
a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[4] = a10 * c + a20 * s;
out[5] = a11 * c + a21 * s;
out[6] = a12 * c + a22 * s;
out[7] = a13 * c + a23 * s;
out[8] = a20 * c - a10 * s;
out[9] = a21 * c - a11 * s;
out[10] = a22 * c - a12 * s;
out[11] = a23 * c - a13 * s;
return out;
};
/**
* Rotates a matrix by the given angle around the Y axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateY = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a00 = a[0],
a01 = a[1],
a02 = a[2],
a03 = a[3],
a20 = a[8],
a21 = a[9],
a22 = a[10],
a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c - a20 * s;
out[1] = a01 * c - a21 * s;
out[2] = a02 * c - a22 * s;
out[3] = a03 * c - a23 * s;
out[8] = a00 * s + a20 * c;
out[9] = a01 * s + a21 * c;
out[10] = a02 * s + a22 * c;
out[11] = a03 * s + a23 * c;
return out;
};
/**
* Rotates a matrix by the given angle around the Z axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
mat4.rotateZ = function (out, a, rad) {
var s = Math.sin(rad),
c = Math.cos(rad),
a00 = a[0],
a01 = a[1],
a02 = a[2],
a03 = a[3],
a10 = a[4],
a11 = a[5],
a12 = a[6],
a13 = a[7];
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c + a10 * s;
out[1] = a01 * c + a11 * s;
out[2] = a02 * c + a12 * s;
out[3] = a03 * c + a13 * s;
out[4] = a10 * c - a00 * s;
out[5] = a11 * c - a01 * s;
out[6] = a12 * c - a02 * s;
out[7] = a13 * c - a03 * s;
return out;
};
/**
* Creates a matrix from a quaternion rotation and vector translation
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, vec);
* var quatMat = mat4.create();
* quat4.toMat4(quat, quatMat);
* mat4.multiply(dest, quatMat);
*
* @param {mat4} out mat4 receiving operation result
* @param {quat4} q Rotation quaternion
* @param {vec3} v Translation vector
* @returns {mat4} out
*/
mat4.fromRotationTranslation = function (out, q, v) {
// Quaternion math
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
xy = x * y2,
xz = x * z2,
yy = y * y2,
yz = y * z2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - (yy + zz);
out[1] = xy + wz;
out[2] = xz - wy;
out[3] = 0;
out[4] = xy - wz;
out[5] = 1 - (xx + zz);
out[6] = yz + wx;
out[7] = 0;
out[8] = xz + wy;
out[9] = yz - wx;
out[10] = 1 - (xx + yy);
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
};
mat4.fromQuat = function (out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
yx = y * x2,
yy = y * y2,
zx = z * x2,
zy = z * y2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
wz = w * z2;
out[0] = 1 - yy - zz;
out[1] = yx + wz;
out[2] = zx - wy;
out[3] = 0;
out[4] = yx - wz;
out[5] = 1 - xx - zz;
out[6] = zy + wx;
out[7] = 0;
out[8] = zx + wy;
out[9] = zy - wx;
out[10] = 1 - xx - yy;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
};
/**
* Generates a frustum matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {Number} left Left bound of the frustum
* @param {Number} right Right bound of the frustum
* @param {Number} bottom Bottom bound of the frustum
* @param {Number} top Top bound of the frustum
* @param {Number} near Near bound of the frustum
* @param {Number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.frustum = function (out, left, right, bottom, top, near, far) {
var rl = 1 / (right - left),
tb = 1 / (top - bottom),
nf = 1 / (near - far);
out[0] = (near * 2) * rl;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = (near * 2) * tb;
out[6] = 0;
out[7] = 0;
out[8] = (right + left) * rl;
out[9] = (top + bottom) * tb;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (far * near * 2) * nf;
out[15] = 0;
return out;
};
/**
* Generates a perspective projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} fovy Vertical field of view in radians
* @param {number} aspect Aspect ratio. typically viewport width/height
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.perspective = function (out, fovy, aspect, near, far) {
var f = 1.0 / Math.tan(fovy / 2),
nf = 1 / (near - far);
out[0] = f / aspect;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = f;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (2 * far * near) * nf;
out[15] = 0;
return out;
};
/**
* Generates a orthogonal projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} left Left bound of the frustum
* @param {number} right Right bound of the frustum
* @param {number} bottom Bottom bound of the frustum
* @param {number} top Top bound of the frustum
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.ortho = function (out, left, right, bottom, top, near, far) {
var lr = 1 / (left - right),
bt = 1 / (bottom - top),
nf = 1 / (near - far);
out[0] = -2 * lr;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = -2 * bt;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 2 * nf;
out[11] = 0;
out[12] = (left + right) * lr;
out[13] = (top + bottom) * bt;
out[14] = (far + near) * nf;
out[15] = 1;
return out;
};
/**
* Generates a look-at matrix with the given eye position, focal point, and up axis
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {vec3} eye Position of the viewer
* @param {vec3} center Point the viewer is looking at
* @param {vec3} up vec3 pointing up
* @returns {mat4} out
*/
mat4.lookAt = function (out, eye, center, up) {
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
Math.abs(eyey - centery) < GLMAT_EPSILON &&
Math.abs(eyez - centerz) < GLMAT_EPSILON) {
return mat4.identity(out);
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
return out;
};
/**
* Returns a string representation of a mat4
*
* @param {mat4} mat matrix to represent as a string
* @returns {String} string representation of the matrix
*/
mat4.str = function (a) {
return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
};
/**
* Returns Frobenius norm of a mat4
*
* @param {mat4} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
mat4.frob = function (a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
};
if(typeof(exports) !== 'undefined') {
exports.mat4 = mat4;
}
;
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* @class Quaternion
* @name quat
*/
var quat = {};
/**
* Creates a new identity quat
*
* @returns {quat} a new quaternion
*/
quat.create = function() {
var out = new GLMAT_ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Sets a quaternion to represent the shortest rotation from one
* vector to another.
*
* Both vectors are assumed to be unit length.
*
* @param {quat} out the receiving quaternion.
* @param {vec3} a the initial vector
* @param {vec3} b the destination vector
* @returns {quat} out
*/
quat.rotationTo = (function() {
var tmpvec3 = vec3.create();
var xUnitVec3 = vec3.fromValues(1,0,0);
var yUnitVec3 = vec3.fromValues(0,1,0);
return function(out, a, b) {
var dot = vec3.dot(a, b);
if (dot < -0.999999) {
vec3.cross(tmpvec3, xUnitVec3, a);
if (vec3.length(tmpvec3) < 0.000001)
vec3.cross(tmpvec3, yUnitVec3, a);
vec3.normalize(tmpvec3, tmpvec3);
quat.setAxisAngle(out, tmpvec3, Math.PI);
return out;
} else if (dot > 0.999999) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
} else {
vec3.cross(tmpvec3, a, b);
out[0] = tmpvec3[0];
out[1] = tmpvec3[1];
out[2] = tmpvec3[2];
out[3] = 1 + dot;
return quat.normalize(out, out);
}
};
})();
/**
* Sets the specified quaternion with values corresponding to the given
* axes. Each axis is a vec3 and is expected to be unit length and
* perpendicular to all other specified axes.
*
* @param {vec3} view the vector representing the viewing direction
* @param {vec3} right the vector representing the local "right" direction
* @param {vec3} up the vector representing the local "up" direction
* @returns {quat} out
*/
quat.setAxes = (function() {
var matr = mat3.create();
return function(out, view, right, up) {
matr[0] = right[0];
matr[3] = right[1];
matr[6] = right[2];
matr[1] = up[0];
matr[4] = up[1];
matr[7] = up[2];
matr[2] = -view[0];
matr[5] = -view[1];
matr[8] = -view[2];
return quat.normalize(out, quat.fromMat3(out, matr));
};
})();
/**
* Creates a new quat initialized with values from an existing quaternion
*
* @param {quat} a quaternion to clone
* @returns {quat} a new quaternion
* @function
*/
quat.clone = vec4.clone;
/**
* Creates a new quat initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} a new quaternion
* @function
*/
quat.fromValues = vec4.fromValues;
/**
* Copy the values from one quat to another
*
* @param {quat} out the receiving quaternion
* @param {quat} a the source quaternion
* @returns {quat} out
* @function
*/
quat.copy = vec4.copy;
/**
* Set the components of a quat to the given values
*
* @param {quat} out the receiving quaternion
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} out
* @function
*/
quat.set = vec4.set;
/**
* Set a quat to the identity quaternion
*
* @param {quat} out the receiving quaternion
* @returns {quat} out
*/
quat.identity = function(out) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
};
/**
* Sets a quat from the given angle and rotation axis,
* then returns it.
*
* @param {quat} out the receiving quaternion
* @param {vec3} axis the axis around which to rotate
* @param {Number} rad the angle in radians
* @returns {quat} out
**/
quat.setAxisAngle = function(out, axis, rad) {
rad = rad * 0.5;
var s = Math.sin(rad);
out[0] = s * axis[0];
out[1] = s * axis[1];
out[2] = s * axis[2];
out[3] = Math.cos(rad);
return out;
};
/**
* Adds two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
* @function
*/
quat.add = vec4.add;
/**
* Multiplies two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
*/
quat.multiply = function(out, a, b) {
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = b[0], by = b[1], bz = b[2], bw = b[3];
out[0] = ax * bw + aw * bx + ay * bz - az * by;
out[1] = ay * bw + aw * by + az * bx - ax * bz;
out[2] = az * bw + aw * bz + ax * by - ay * bx;
out[3] = aw * bw - ax * bx - ay * by - az * bz;
return out;
};
/**
* Alias for {@link quat.multiply}
* @function
*/
quat.mul = quat.multiply;
/**
* Scales a quat by a scalar number
*
* @param {quat} out the receiving vector
* @param {quat} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {quat} out
* @function
*/
quat.scale = vec4.scale;
/**
* Rotates a quaternion by the given angle about the X axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateX = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + aw * bx;
out[1] = ay * bw + az * bx;
out[2] = az * bw - ay * bx;
out[3] = aw * bw - ax * bx;
return out;
};
/**
* Rotates a quaternion by the given angle about the Y axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateY = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
by = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw - az * by;
out[1] = ay * bw + aw * by;
out[2] = az * bw + ax * by;
out[3] = aw * bw - ay * by;
return out;
};
/**
* Rotates a quaternion by the given angle about the Z axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
quat.rotateZ = function (out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bz = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + ay * bz;
out[1] = ay * bw - ax * bz;
out[2] = az * bw + aw * bz;
out[3] = aw * bw - az * bz;
return out;
};
/**
* Calculates the W component of a quat from the X, Y, and Z components.
* Assumes that quaternion is 1 unit in length.
* Any existing W component will be ignored.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate W component of
* @returns {quat} out
*/
quat.calculateW = function (out, a) {
var x = a[0], y = a[1], z = a[2];
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
return out;
};
/**
* Calculates the dot product of two quat's
*
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {Number} dot product of a and b
* @function
*/
quat.dot = vec4.dot;
/**
* Performs a linear interpolation between two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {quat} out
* @function
*/
quat.lerp = vec4.lerp;
/**
* Performs a spherical linear interpolation between two quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {quat} out
*/
quat.slerp = function (out, a, b, t) {
// benchmarks:
// http://jsperf.com/quaternion-slerp-implementations
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = b[0], by = b[1], bz = b[2], bw = b[3];
var omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = ax * bx + ay * by + az * bz + aw * bw;
// adjust signs (if necessary)
if ( cosom < 0.0 ) {
cosom = -cosom;
bx = - bx;
by = - by;
bz = - bz;
bw = - bw;
}
// calculate coefficients
if ( (1.0 - cosom) > 0.000001 ) {
// standard case (slerp)
omega = Math.acos(cosom);
sinom = Math.sin(omega);
scale0 = Math.sin((1.0 - t) * omega) / sinom;
scale1 = Math.sin(t * omega) / sinom;
} else {
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0 - t;
scale1 = t;
}
// calculate final values
out[0] = scale0 * ax + scale1 * bx;
out[1] = scale0 * ay + scale1 * by;
out[2] = scale0 * az + scale1 * bz;
out[3] = scale0 * aw + scale1 * bw;
return out;
};
/**
* Calculates the inverse of a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate inverse of
* @returns {quat} out
*/
quat.invert = function(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
invDot = dot ? 1.0/dot : 0;
// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
out[0] = -a0*invDot;
out[1] = -a1*invDot;
out[2] = -a2*invDot;
out[3] = a3*invDot;
return out;
};
/**
* Calculates the conjugate of a quat
* If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate conjugate of
* @returns {quat} out
*/
quat.conjugate = function (out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a[3];
return out;
};
/**
* Calculates the length of a quat
*
* @param {quat} a vector to calculate length of
* @returns {Number} length of a
* @function
*/
quat.length = vec4.length;
/**
* Alias for {@link quat.length}
* @function
*/
quat.len = quat.length;
/**
* Calculates the squared length of a quat
*
* @param {quat} a vector to calculate squared length of
* @returns {Number} squared length of a
* @function
*/
quat.squaredLength = vec4.squaredLength;
/**
* Alias for {@link quat.squaredLength}
* @function
*/
quat.sqrLen = quat.squaredLength;
/**
* Normalize a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quaternion to normalize
* @returns {quat} out
* @function
*/
quat.normalize = vec4.normalize;
/**
* Creates a quaternion from the given 3x3 rotation matrix.
*
* NOTE: The resultant quaternion is not normalized, so you should be sure
* to renormalize the quaternion yourself where necessary.
*
* @param {quat} out the receiving quaternion
* @param {mat3} m rotation matrix
* @returns {quat} out
* @function
*/
quat.fromMat3 = function(out, m) {
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
// article "Quaternion Calculus and Fast Animation".
var fTrace = m[0] + m[4] + m[8];
var fRoot;
if ( fTrace > 0.0 ) {
// |w| > 1/2, may as well choose w > 1/2
fRoot = Math.sqrt(fTrace + 1.0); // 2w
out[3] = 0.5 * fRoot;
fRoot = 0.5/fRoot; // 1/(4w)
out[0] = (m[7]-m[5])*fRoot;
out[1] = (m[2]-m[6])*fRoot;
out[2] = (m[3]-m[1])*fRoot;
} else {
// |w| <= 1/2
var i = 0;
if ( m[4] > m[0] )
i = 1;
if ( m[8] > m[i*3+i] )
i = 2;
var j = (i+1)%3;
var k = (i+2)%3;
fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
out[i] = 0.5 * fRoot;
fRoot = 0.5 / fRoot;
out[3] = (m[k*3+j] - m[j*3+k]) * fRoot;
out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
}
return out;
};
/**
* Returns a string representation of a quatenion
*
* @param {quat} vec vector to represent as a string
* @returns {String} string representation of the vector
*/
quat.str = function (a) {
return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
};
if(typeof(exports) !== 'undefined') {
exports.quat = quat;
}
;
})(shim.exports);
})(this);
},{}],105:[function(require,module,exports){
'use strict';
function constant(value) {
return function() {
return value;
}
}
function interpolateNumber(a, b, t) {
return (a * (1 - t)) + (b * t);
}
function interpolateArray(a, b, t) {
var result = [];
for (var i = 0; i < a.length; i++) {
result[i] = interpolateNumber(a[i], b[i], t);
}
return result;
}
exports['interpolated'] = function(f) {
if (!f.stops) {
return constant(f);
}
var stops = f.stops,
base = f.base || 1,
interpolate = Array.isArray(stops[0][1]) ? interpolateArray : interpolateNumber;
return function(z) {
// find the two stops which the current z is between
var low, high;
for (var i = 0; i < stops.length; i++) {
var stop = stops[i];
if (stop[0] <= z) {
low = stop;
}
if (stop[0] > z) {
high = stop;
break;
}
}
if (low && high) {
var zoomDiff = high[0] - low[0],
zoomProgress = z - low[0],
t = base === 1 ?
zoomProgress / zoomDiff :
(Math.pow(base, zoomProgress) - 1) / (Math.pow(base, zoomDiff) - 1);
return interpolate(low[1], high[1], t);
} else if (low) {
return low[1];
} else if (high) {
return high[1];
}
};
};
exports['piecewise-constant'] = function(f) {
if (!f.stops) {
return constant(f);
}
var stops = f.stops;
return function(z) {
for (var i = 0; i < stops.length; i++) {
if (stops[i][0] > z) {
return stops[i === 0 ? 0 : i - 1][1];
}
}
return stops[stops.length - 1][1];
}
};
},{}],106:[function(require,module,exports){
'use strict';
var reference = require('../../reference/latest.js');
var validate = require('./parsed');
module.exports = function(style) {
return validate(style, reference);
};
},{"../../reference/latest.js":108,"./parsed":107}],107:[function(require,module,exports){
'use strict';
var parseCSSColor = require('csscolorparser').parseCSSColor;
var format = require('util').format;
module.exports = function(style, reference) {
var constants = style.constants || {},
layers = {},
errors = [];
function error(key, val /*, message, ...*/) {
var err = {
message: (key ? key + ': ' : '') +
format.apply(format, Array.prototype.slice.call(arguments, 2))
};
if (val !== null && val !== undefined && val.__line__) {
err.line = val.__line__;
}
errors.push(err);
}
// Main recursive validation function. Tracks:
//
// - key: string representing location of validation in style tree. Used only
// for more informative error reporting.
// - val: current value from style being evaluated. May be anything from a
// high level object that needs to be descended into deeper or a simple
// scalar value.
// - spec: current spec being evaluated. Tracks val.
//
function validate(key, val, spec) {
var type = typeof_(val);
// Constants
if (type === 'string' && val[0] === '@') {
if (!(val in constants)) {
return error(key, val, 'constant "%s" not found', val);
}
val = constants[val];
type = typeof_(val);
}
// Functions
if (spec.function && type === 'object') {
return validate.function(key, val, spec);
}
if (spec.type) {
var validator = validate[spec.type];
if (validator) {
return validator(key, val, spec);
}
spec = reference[spec.type];
}
validate.object(key, val, spec);
}
validate.constants = function(key, val) {
var type = typeof_(val);
if (type !== 'object') {
return error(key, val, 'object expected, %s found', type);
}
for (var k in val) {
if (k[0] !== '@') {
error(key + '.' + k, val[k], 'constants must start with "@"');
}
}
};
validate.source = function(key, val) {
if (!val.type) {
error(key, val, '"type" is required');
return;
}
var type = unbundle(val.type);
switch (type) {
case 'vector':
case 'raster':
validate.object(key, val, reference.source_tile);
if ('url' in val) {
for (var prop in val) {
if (['type', 'url', 'tileSize'].indexOf(prop) < 0) {
error(key + '.' + prop, val[prop], 'a source with a "url" property may not include a "%s" property', prop);
}
}
}
break;
case 'geojson':
validate.object(key, val, reference.source_geojson);
break;
case 'video':
validate.object(key, val, reference.source_video);
break;
default:
validate.enum(key + '.type', val.type, {values: ['vector', 'raster', 'geojson', 'video']});
}
};
validate.layer = function(key, val) {
if (!val.type && !val.ref) {
error(key, val, 'either "type" or "ref" is required');
}
var type = unbundle(val.type),
ref = unbundle(val.ref);
if (val.id) {
if (layers[val.id]) {
error(key, val.id, 'duplicate layer id "%s", previously used at line %d', val.id, layers[val.id]);
} else {
layers[val.id] = val.id.__line__;
}
}
if ('ref' in val) {
['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) {
if (p in val) {
error(key, val[p], '"%s" is prohibited for ref layers', p);
}
});
var parent;
style.layers.forEach(function(layer) {
if (layer.id == ref) parent = layer;
});
if (!parent) {
error(key, val.ref, 'ref layer "%s" not found', ref);
} else if (parent.ref) {
error(key, val.ref, 'ref cannot reference another ref layer');
} else {
type = parent.type;
}
} else if (type !== 'background') {
if (!val.source) {
error(key, val, 'missing required property "source"');
} else {
var source = style.sources[val.source];
if (!source) {
error(key, val.source, 'source "%s" not found', val.source);
} else if (source.type == 'vector' && type == 'raster') {
error(key, val.source, 'layer "%s" requires a raster source', val.id);
} else if (source.type == 'raster' && type != 'raster') {
error(key, val.source, 'layer "%s" requires a vector source', val.id);
}
}
}
validate.object(key, val, reference.layer, {
filter: validate.filter,
layout: function(key, val) {
var spec = reference['layout_' + type];
return type && spec && validate(key, val, spec);
},
paint: function(key, val) {
var spec = reference['paint_' + type];
return type && spec && validate(key, val, spec);
}
});
};
validate.object = function (key, val, spec, validators) {
validators = validators || {};
var type = typeof_(val);
if (type !== 'object') {
return error(key, val, 'object expected, %s found', type);
}
for (var k in val) {
var speckey = k.split('.')[0]; // treat 'paint.*' as 'paint'
var def = spec[speckey] || spec['*'];
var transition = speckey.match(/^(.*)-transition$/);
if (def) {
(validators[speckey] || validate)((key ? key + '.' : key) + k, val[k], def);
} else if (transition && spec[transition[1]] && spec[transition[1]].transition) {
validate((key ? key + '.' : key) + k, val[k], reference.transition);
// tolerate root-level extra keys & arbitrary layer properties
} else if (key !== '' && key.split('.').length !== 1) {
error(key, val[k], 'unknown property "%s"', k);
}
}
for (var l in spec) {
if (spec[l].required && spec[l]['default'] === undefined && val[l] === undefined) {
error(key, val, 'missing required property "%s"', l);
}
}
};
validate.array = function (key, val, spec, validator) {
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (spec.length && val.length !== spec.length) {
return error(key, val, 'array length %d expected, length %d found', spec.length, val.length);
}
var value = {
"type": spec.value
};
if (style.version < 7) {
value.function = spec.function;
}
if (typeof_(spec.value) === 'object') {
value = spec.value;
}
for (var i = 0; i < val.length; i++) {
(validator || validate)(key + '[' + i + ']', val[i], value);
}
};
validate.filter = function(key, val) {
var type;
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (val.length < 1) {
return error(key, val, 'filter array must have at least 1 element');
}
validate.enum(key + '[0]', val[0], reference.filter_operator);
switch (unbundle(val[0])) {
case '<':
case '<=':
case '>':
case '>=':
if (val.length >= 2 && val[1] == '$type') {
error(key, val, '"$type" cannot be use with operator "%s"', val[0]);
}
/* falls through */
case '==':
case '!=':
if (val.length != 3) {
error(key, val, 'filter array for operator "%s" must have 3 elements', val[0]);
}
/* falls through */
case 'in':
case '!in':
if (val.length >= 2) {
type = typeof_(val[1]);
if (type !== 'string') {
error(key + '[1]', val[1], 'string expected, %s found', type);
} else if (val[1][0] === '@') {
error(key + '[1]', val[1], 'filter key cannot be a constant');
}
}
for (var i = 2; i < val.length; i++) {
type = typeof_(val[i]);
if (val[1] == '$type') {
validate.enum(key + '[' + i + ']', val[i], reference.geometry_type);
} else if (type === 'string' && val[i][0] === '@') {
error(key + '[' + i + ']', val[i], 'filter value cannot be a constant');
} else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
error(key + '[' + i + ']', val[i], 'string, number, or boolean expected, %s found', type);
}
}
break;
case 'any':
case 'all':
case 'none':
for (i = 1; i < val.length; i++) {
validate.filter(key + '[' + i + ']', val[i]);
}
break;
}
};
validate.function = function(key, val, spec) {
validate.object(key, val, reference.function, {
stops: function (key, val, arraySpec) {
var lastStop = -Infinity;
validate.array(key, val, arraySpec, function validateStop(key, val) {
if (typeof_(val) !== 'array') {
return error(key, val, 'array expected, %s found', typeof_(val));
}
if (val.length !== 2) {
return error(key, val, 'array length %d expected, length %d found', 2, val.length);
}
validate(key + '[0]', val[0], {type: 'number'});
validate(key + '[1]', val[1], spec);
if (typeof_(val[0]) === 'number') {
if (spec.function === 'piecewise-constant' && val[0] % 1 !== 0) {
error(key + '[0]', val[0], 'zoom level for piecewise-constant functions must be an integer');
}
if (val[0] < lastStop) {
error(key + '[0]', val[0], 'array stops must appear in ascending order');
}
lastStop = val[0];
}
});
if (typeof_(val) === 'array' && val.length === 0) {
error(key, val, 'array must have at least one stop');
}
}
});
};
validate.enum = function (key, val, spec) {
if (spec.values.indexOf(unbundle(val)) === -1) {
error(key, val, 'expected one of [%s], %s found', spec.values.join(', '), val);
}
};
validate.color = function(key, val) {
var type = typeof_(val);
if (type !== 'string') {
error(key, val, 'color expected, %s found', type);
} else if (parseCSSColor(val) === null) {
error(key, val, 'color expected, "%s" found', val);
}
};
function typeValidator(expected) {
return function(key, val, spec) {
var actual = typeof_(val);
if (actual !== expected) {
error(key, val, '%s expected, %s found', expected, actual);
}
if ('minimum' in spec && val < spec.minimum) {
error(key, val, '%s is less than the minimum value %s', val, spec.minimum);
}
if ('maximum' in spec && val > spec.maximum) {
error(key, val, '%s is greater than the maximum value %s', val, spec.maximum);
}
};
}
validate.number = typeValidator('number');
validate.string = typeValidator('string');
validate.boolean = typeValidator('boolean');
validate['*'] = function() {};
validate('', style, reference.$root);
return errors;
};
function typeof_(val) {
if (val instanceof Number)
return 'number';
if (val instanceof String)
return 'string';
if (val instanceof Boolean)
return 'boolean';
if (Array.isArray(val))
return 'array';
if (val === null)
return 'null';
return typeof val;
}
function unbundle(_) {
if (_ instanceof Number ||
_ instanceof String ||
_ instanceof Boolean) {
return _.valueOf();
} else {
return _;
}
}
},{"csscolorparser":97,"util":124}],108:[function(require,module,exports){
module.exports = require('./v7.json');
},{"./v7.json":109}],109:[function(require,module,exports){
module.exports={
"$version": 7,
"$root": {
"version": {
"required": true,
"type": "enum",
"values": [
7
],
"doc": "Stylesheet version number. Must be 7."
},
"name": {
"type": "string",
"doc": "A human-readable name for the style."
},
"constants": {
"type": "constants",
"doc": "An object of constants to be referenced in layers."
},
"sources": {
"required": true,
"type": "sources",
"doc": "Data source specifications."
},
"sprite": {
"type": "string",
"doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended."
},
"glyphs": {
"type": "string",
"doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}."
},
"transition": {
"type": "transition",
"doc": "A global transition definition to use as a default across properties."
},
"layers": {
"required": true,
"type": "array",
"value": "layer",
"doc": "Layers will be drawn in the order of this array."
}
},
"constants": {
"*": {
"type": "*",
"doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol."
}
},
"sources": {
"*": {
"type": "source",
"doc": "Specification of a data source. For vector and raster sources, either TileJSON or a URL to a TileJSON must be provided. For GeoJSON and video sources, a URL must be provided."
}
},
"source": [
"source_tile",
"source_geojson",
"source_video"
],
"source_tile": {
"type": {
"required": true,
"type": "enum",
"values": [
"vector",
"raster"
],
"doc": "The data type of the source."
},
"url": {
"type": "string",
"doc": "A URL to a TileJSON resource. Supported protocols are `http:`, `https:`, and `mapbox://<mapid>`."
},
"tiles": {
"type": "array",
"value": "string",
"doc": "An array of one or more tile source URLs, as in the TileJSON spec."
},
"minzoom": {
"type": "number",
"default": 0,
"doc": "Minimum zoom level for which tiles are available, as in the TileJSON spec."
},
"maxzoom": {
"type": "number",
"default": 22,
"doc": "Maximum zoom level for which tiles are available, as in the TileJSON spec. Data from tiles at the maxzoom are used when displaying the map at higher zoom levels."
},
"tileSize": {
"type": "number",
"default": 512,
"units": "pixels",
"doc": "The minimum visual size to display tiles for this layer. Only configurable for raster layers."
},
"*": {
"type": "*",
"doc": "Other keys to configure the data source."
}
},
"source_geojson": {
"type": {
"required": true,
"type": "enum",
"values": [
"geojson"
]
},
"data": {
"type": "*"
}
},
"source_video": {
"type": {
"required": true,
"type": "enum",
"values": [
"video"
]
},
"url": {
"required": true,
"type": "array",
"value": "string",
"doc": "URLs to video content in order of preferred format."
},
"coordinates": {
"required": true,
"type": "array",
"length": 4,
"value": {
"type": "array",
"length": 2,
"value": "number"
}
}
},
"layer": {
"id": {
"type": "string",
"doc": "Unique layer name."
},
"type": {
"type": "enum",
"values": [
"fill",
"line",
"symbol",
"raster",
"background"
],
"doc": "Rendering type of this layer."
},
"ref": {
"type": "string",
"doc": "References another layer to copy `type`, `source`, `source-layer`, `minzoom`, `maxzoom`, `filter`, and `layout` properties from. This allows the layers to share processing and be more efficient."
},
"source": {
"type": "string",
"doc": "Name of a source description to be used for this layer."
},
"source-layer": {
"type": "string",
"doc": "Layer to use from a vector tile source. Required if the source supports multiple layers."
},
"minzoom": {
"type": "number",
"minimum": 0,
"maximum": 22,
"doc": "The minimum zoom level on which the layer gets parsed and appears on."
},
"maxzoom": {
"type": "number",
"minimum": 0,
"maximum": 22,
"doc": "The maximum zoom level on which the layer gets parsed and appears on."
},
"interactive": {
"type": "boolean",
"doc": "Enable querying of feature data from this layer for interactivity.",
"default": false
},
"filter": {
"type": "filter",
"doc": "A expression specifying conditions on source features. Only features that match the filter are displayed."
},
"layout": {
"type": "layout",
"doc": "Layout properties for the layer."
},
"paint": {
"type": "paint",
"doc": "Default paint properties for this layer."
},
"paint.*": {
"type": "paint",
"doc": "Class-specific paint properties for this layer. The class name is the part after the first dot."
}
},
"layout": [
"layout_fill",
"layout_line",
"layout_symbol",
"layout_raster",
"layout_background"
],
"layout_background": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_fill": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_line": {
"line-cap": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"butt",
"round",
"square"
],
"default": "butt",
"doc": "The display of line endings."
},
"line-join": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"bevel",
"round",
"miter"
],
"default": "miter",
"doc": "The display of lines when joining."
},
"line-miter-limit": {
"type": "number",
"default": 2,
"function": "interpolated",
"doc": "Used to automatically convert miter joins to bevel joins for sharp angles.",
"requires": [
{
"line-join": "miter"
}
]
},
"line-round-limit": {
"type": "number",
"default": 1,
"function": "interpolated",
"doc": "Used to automatically convert round joins to miter joins for shallow angles.",
"requires": [
{
"line-join": "round"
}
]
},
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_symbol": {
"symbol-placement": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"point",
"line"
],
"default": "point",
"doc": "Label placement relative to its geometry. `line` can only be used on LineStrings and Polygons."
},
"symbol-min-distance": {
"type": "number",
"default": 250,
"minimum": 1,
"function": "interpolated",
"units": "pixels",
"doc": "Minimum distance between two symbol anchors.",
"requires": [
{
"symbol-placement": "line"
}
]
},
"symbol-avoid-edges": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer."
},
"icon-allow-overlap": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon will be visible even if it collides with other icons and text.",
"requires": [
"icon-image"
]
},
"icon-ignore-placement": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon won't affect placement of other icons and text.",
"requires": [
"icon-image"
]
},
"icon-optional": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbol will appear without its icon, in spaces where the icon would make it too large to fit.",
"requires": [
"icon-image",
"text-field"
]
},
"icon-rotation-alignment": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"default": "viewport",
"doc": "Orientation of icon when map is rotated.",
"requires": [
"icon-image"
]
},
"icon-max-size": {
"type": "number",
"default": 1,
"minimum": 0,
"function": "interpolated",
"doc": "The maximum factor to scale the icon.",
"requires": [
"icon-image"
]
},
"icon-image": {
"type": "string",
"function": "piecewise-constant",
"doc": "A string with {tokens} replaced, referencing the data property to pull from.",
"tokens": true
},
"icon-rotate": {
"type": "number",
"default": 0,
"period": 360,
"function": "interpolated",
"units": "degrees",
"doc": "Rotates the icon clockwise.",
"requires": [
"icon-image"
]
},
"icon-padding": {
"type": "number",
"default": 2,
"minimum": 0,
"function": "interpolated",
"units": "pixels",
"doc": "Padding value around icon bounding box to avoid icon collisions.",
"requires": [
"icon-image"
]
},
"icon-keep-upright": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the icon may be flipped to prevent it from being rendered upside-down",
"requires": [
"icon-image",
{
"icon-rotation-alignment": "map"
}
]
},
"icon-offset": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"doc": "Icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"icon-image"
]
},
"text-rotation-alignment": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"default": "viewport",
"doc": "Orientation of icon or text when map is rotated.",
"requires": [
"text-field"
]
},
"text-field": {
"type": "string",
"function": "piecewise-constant",
"default": "",
"tokens": true,
"doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}."
},
"text-font": {
"type": "string",
"function": "piecewise-constant",
"default": "Open Sans Regular, Arial Unicode MS Regular",
"doc": "Font stack to use for displaying text.",
"requires": [
"text-field"
]
},
"text-max-size": {
"type": "number",
"default": 16,
"minimum": 0,
"units": "pixels",
"function": "interpolated",
"doc": "The maximum size text will be laid out, to calculate collisions with.",
"requires": [
"text-field"
]
},
"text-max-width": {
"type": "number",
"default": 15,
"minimum": 0,
"units": "em",
"function": "interpolated",
"doc": "The maximum line width for text wrapping.",
"requires": [
"text-field"
]
},
"text-line-height": {
"type": "number",
"default": 1.2,
"units": "em",
"function": "interpolated",
"doc": "Text leading value for multi-line text.",
"requires": [
"text-field"
]
},
"text-letter-spacing": {
"type": "number",
"default": 0,
"units": "em",
"function": "interpolated",
"doc": "Text kerning value.",
"requires": [
"text-field"
]
},
"text-justify": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"left",
"center",
"right"
],
"default": "center",
"doc": "Text justification options.",
"requires": [
"text-field"
]
},
"text-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"center",
"left",
"right",
"top",
"bottom",
"top-left",
"top-right",
"bottom-left",
"bottom-right"
],
"default": "center",
"doc": "Which part of the text to place closest to the anchor.",
"requires": [
"text-field"
]
},
"text-max-angle": {
"type": "number",
"default": 45,
"units": "degrees",
"function": "interpolated",
"doc": "Maximum angle change between adjacent characters.",
"requires": [
"text-field",
{
"symbol-placement": "line"
}
]
},
"text-rotate": {
"type": "number",
"default": 0,
"period": 360,
"units": "degrees",
"function": "interpolated",
"doc": "Rotates the text clockwise.",
"requires": [
"text-field"
]
},
"text-padding": {
"type": "number",
"default": 2,
"minimum": 0,
"units": "pixels",
"function": "interpolated",
"doc": "Padding value around text bounding box to avoid label collisions.",
"requires": [
"text-field"
]
},
"text-keep-upright": {
"type": "boolean",
"function": "piecewise-constant",
"default": true,
"doc": "If true, the text may be flipped vertically to prevent it from being rendered upside-down.",
"requires": [
"text-field",
{
"text-rotation-alignment": "map"
}
]
},
"text-transform": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"none",
"uppercase",
"lowercase"
],
"default": "none",
"doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property.",
"requires": [
"text-field"
]
},
"text-offset": {
"type": "array",
"doc": "Specifies the distance that text is offset from its anchor horizontally and vertically.",
"value": "number",
"units": "ems",
"function": "interpolated",
"length": 2,
"default": [
0,
0
],
"requires": [
"text-field"
]
},
"text-allow-overlap": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the text will be visible even if it collides with other icons and labels.",
"requires": [
"text-field"
]
},
"text-ignore-placement": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the text won't affect placement of other icons and labels.",
"requires": [
"text-field"
]
},
"text-optional": {
"type": "boolean",
"function": "piecewise-constant",
"default": false,
"doc": "If true, the symbol will appear without its text, in spaces where the text would make it too large to fit.",
"requires": [
"text-field",
"icon-image"
]
},
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"layout_raster": {
"visibility": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"visible",
"none"
],
"default": "visible",
"doc": "The display of this layer. `none` hides this layer."
}
},
"filter": {
"type": "array",
"value": "*"
},
"filter_operator": {
"type": "enum",
"values": [
"==",
"!=",
">",
">=",
"<",
"<=",
"in",
"!in",
"all",
"any",
"none"
]
},
"geometry_type": {
"type": "enum",
"values": [
"Point",
"LineString",
"Polygon"
]
},
"function": {
"stops": {
"type": "array",
"required": true,
"doc": "An array of stops.",
"value": "function_stop"
},
"base": {
"type": "number",
"default": 1,
"minimum": 0,
"doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly."
}
},
"function_stop": {
"type": "array",
"minimum": 0,
"maximum": 22,
"value": [
"number",
"color"
],
"length": 2,
"doc": "Zoom level and value pair."
},
"paint": [
"paint_fill",
"paint_line",
"paint_symbol",
"paint_raster",
"paint_background"
],
"paint_fill": {
"fill-antialias": {
"type": "boolean",
"function": "piecewise-constant",
"default": true,
"doc": "Whether or not the fill should be antialiased."
},
"fill-opacity": {
"type": "number",
"function": "interpolated",
"default": 1,
"minimum": 0,
"maximum": 1,
"doc": "The opacity given to the fill color.",
"transition": true
},
"fill-color": {
"type": "color",
"default": "#000000",
"doc": "The color of the fill.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "fill-image"
}
]
},
"fill-outline-color": {
"type": "color",
"doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "fill-image"
},
{
"fill-antialias": true
}
]
},
"fill-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively."
},
"fill-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"fill-translate"
]
},
"fill-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Name of image in sprite to use for drawing image fills."
}
},
"paint_line": {
"line-opacity": {
"type": "number",
"doc": "The opacity at which the line will be drawn.",
"function": "interpolated",
"default": 1,
"minimum": 0,
"maximum": 1,
"transition": true
},
"line-color": {
"type": "color",
"doc": "The color with which the line will be drawn.",
"default": "#000000",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "line-image"
}
]
},
"line-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively."
},
"line-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"line-translate"
]
},
"line-width": {
"type": "number",
"default": 1,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Stroke thickness."
},
"line-gap-width": {
"type": "number",
"default": 0,
"minimum": 0,
"doc": "Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.",
"function": "interpolated",
"transition": true,
"units": "pixels"
},
"line-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Blur applied to the line, in pixels."
},
"line-dasharray": {
"type": "array",
"function": "piecewise-constant",
"value": "number",
"doc": "Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.",
"minimum": 0,
"transition": true,
"units": "line widths",
"requires": [
{
"!": "line-image"
}
]
},
"line-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Name of image in sprite to use for drawing image lines."
}
},
"paint_symbol": {
"icon-opacity": {
"doc": "The opacity at which the icon will be drawn.",
"type": "number",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true,
"requires": [
"icon-image"
]
},
"icon-size": {
"type": "number",
"default": 1,
"function": "interpolated",
"transition": true,
"doc": "Scale factor for icon. 1 is original size, 3 triples the size.",
"requires": [
"icon-image"
]
},
"icon-color": {
"type": "color",
"default": "#000000",
"function": "interpolated",
"transition": true,
"doc": "The color of the icon. This can only be used with sdf icons.",
"requires": [
"icon-image"
]
},
"icon-halo-color": {
"type": "color",
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"transition": true,
"doc": "The color of the icon's halo. Icon halos can only be used with sdf icons.",
"requires": [
"icon-image"
]
},
"icon-halo-width": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the icon outline.",
"requires": [
"icon-image"
]
},
"icon-halo-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Fade out the halo towards the outside.",
"requires": [
"icon-image"
]
},
"icon-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "An icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"icon-image"
]
},
"icon-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"icon-image",
"icon-translate"
]
},
"text-opacity": {
"type": "number",
"doc": "The opacity at which the text will be drawn.",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true,
"requires": [
"text-field"
]
},
"text-size": {
"type": "number",
"default": 16,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Font size. If unspecified, the text will be as big as allowed by the layer definition.",
"requires": [
"text-field"
]
},
"text-color": {
"type": "color",
"doc": "The color with which the text will be drawn.",
"default": "#000000",
"function": "interpolated",
"transition": true,
"requires": [
"text-field"
]
},
"text-halo-color": {
"type": "color",
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"transition": true,
"doc": "The color of the text's halo, which helps it stand out from backgrounds.",
"requires": [
"text-field"
]
},
"text-halo-width": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.",
"requires": [
"text-field"
]
},
"text-halo-blur": {
"type": "number",
"default": 0,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "The halo's fadeout distance towards the outside.",
"requires": [
"text-field"
]
},
"text-translate": {
"type": "array",
"value": "number",
"length": 2,
"default": [
0,
0
],
"function": "interpolated",
"transition": true,
"units": "pixels",
"doc": "Label offset. Values are [x, y] where negatives indicate left and up, respectively.",
"requires": [
"text-field"
]
},
"text-translate-anchor": {
"type": "enum",
"function": "piecewise-constant",
"values": [
"map",
"viewport"
],
"doc": "Control whether the translation is relative to the map (north) or viewport (screen)",
"default": "map",
"requires": [
"text-field",
"text-translate"
]
}
},
"paint_raster": {
"raster-opacity": {
"type": "number",
"doc": "The opacity at which the image will be drawn.",
"default": 1,
"minimum": 0,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-hue-rotate": {
"type": "number",
"default": 0,
"period": 360,
"function": "interpolated",
"transition": true,
"units": "degrees",
"doc": "Rotates hues around the color wheel."
},
"raster-brightness-min": {
"type": "number",
"function": "interpolated",
"doc": "Increase or reduce the brightness of the image. The value is the minimum brightness.",
"default": 0,
"minimum": 0,
"maximum": 1,
"transition": true
},
"raster-brightness-max": {
"type": "number",
"function": "interpolated",
"doc": "Increase or reduce the brightness of the image. The value is the maximum brightness.",
"default": 1,
"minimum": 0,
"maximum": 1,
"transition": true
},
"raster-saturation": {
"type": "number",
"doc": "Increase or reduce the saturation of the image.",
"default": 0,
"minimum": -1,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-contrast": {
"type": "number",
"doc": "Increase or reduce the contrast of the image.",
"default": 0,
"minimum": -1,
"maximum": 1,
"function": "interpolated",
"transition": true
},
"raster-fade-duration": {
"type": "number",
"default": 300,
"minimum": 0,
"function": "interpolated",
"transition": true,
"units": "milliseconds",
"doc": "Fade duration when a new tile is added."
}
},
"paint_background": {
"background-color": {
"type": "color",
"default": "#000000",
"doc": "The color with which the background will be drawn.",
"function": "interpolated",
"transition": true,
"requires": [
{
"!": "background-image"
}
]
},
"background-image": {
"type": "string",
"function": "piecewise-constant",
"transition": true,
"doc": "Optionally an image which is drawn as the background."
},
"background-opacity": {
"type": "number",
"default": 1,
"minimum": 0,
"maximum": 1,
"doc": "The opacity at which the background will be drawn.",
"function": "interpolated",
"transition": true
}
},
"transition": {
"duration": {
"type": "number",
"default": 300,
"minimum": 0,
"units": "milliseconds",
"doc": "Time allotted for transitions to complete."
},
"delay": {
"type": "number",
"default": 0,
"minimum": 0,
"units": "milliseconds",
"doc": "Length of time before a transition begins."
}
}
}
},{}],110:[function(require,module,exports){
'use strict';
// lightweight Buffer shim for pbf browser build
// based on code from github.com/feross/buffer (MIT-licensed)
module.exports = Buffer;
var ieee754 = require('ieee754');
var BufferMethods;
function Buffer(length) {
var arr;
if (length && length.length) {
arr = length;
length = arr.length;
}
var buf = new Uint8Array(length || 0);
if (arr) buf.set(arr);
buf.readUInt32LE = BufferMethods.readUInt32LE;
buf.writeUInt32LE = BufferMethods.writeUInt32LE;
buf.readInt32LE = BufferMethods.readInt32LE;
buf.writeInt32LE = BufferMethods.writeInt32LE;
buf.readFloatLE = BufferMethods.readFloatLE;
buf.writeFloatLE = BufferMethods.writeFloatLE;
buf.readDoubleLE = BufferMethods.readDoubleLE;
buf.writeDoubleLE = BufferMethods.writeDoubleLE;
buf.toString = BufferMethods.toString;
buf.write = BufferMethods.write;
buf.slice = BufferMethods.slice;
buf.copy = BufferMethods.copy;
buf._isBuffer = true;
return buf;
}
var lastStr, lastStrEncoded;
BufferMethods = {
readUInt32LE: function(pos) {
return ((this[pos]) |
(this[pos + 1] << 8) |
(this[pos + 2] << 16)) +
(this[pos + 3] * 0x1000000);
},
writeUInt32LE: function(val, pos) {
this[pos] = val;
this[pos + 1] = (val >>> 8);
this[pos + 2] = (val >>> 16);
this[pos + 3] = (val >>> 24);
},
readInt32LE: function(pos) {
return ((this[pos]) |
(this[pos + 1] << 8) |
(this[pos + 2] << 16)) +
(this[pos + 3] << 24);
},
readFloatLE: function(pos) { return ieee754.read(this, pos, true, 23, 4); },
readDoubleLE: function(pos) { return ieee754.read(this, pos, true, 52, 8); },
writeFloatLE: function(val, pos) { return ieee754.write(this, val, pos, true, 23, 4); },
writeDoubleLE: function(val, pos) { return ieee754.write(this, val, pos, true, 52, 8); },
toString: function(encoding, start, end) {
var str = '',
tmp = '';
start = start || 0;
end = Math.min(this.length, end || this.length);
for (var i = start; i < end; i++) {
var ch = this[i];
if (ch <= 0x7F) {
str += decodeURIComponent(tmp) + String.fromCharCode(ch);
tmp = '';
} else {
tmp += '%' + ch.toString(16);
}
}
str += decodeURIComponent(tmp);
return str;
},
write: function(str, pos) {
var bytes = str === lastStr ? lastStrEncoded : encodeString(str);
for (var i = 0; i < bytes.length; i++) {
this[pos + i] = bytes[i];
}
},
slice: function(start, end) {
return this.subarray(start, end);
},
copy: function(buf, pos) {
pos = pos || 0;
for (var i = 0; i < this.length; i++) {
buf[pos + i] = this[i];
}
}
};
BufferMethods.writeInt32LE = BufferMethods.writeUInt32LE;
Buffer.byteLength = function(str) {
lastStr = str;
lastStrEncoded = encodeString(str);
return lastStrEncoded.length;
};
Buffer.isBuffer = function(buf) {
return !!(buf && buf._isBuffer);
};
function encodeString(str) {
var length = str.length,
bytes = [];
for (var i = 0, c, lead; i < length; i++) {
c = str.charCodeAt(i); // code point
if (c > 0xD7FF && c < 0xE000) {
if (lead) {
if (c < 0xDC00) {
bytes.push(0xEF, 0xBF, 0xBD);
lead = c;
continue;
} else {
c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
lead = null;
}
} else {
if (c > 0xDBFF || (i + 1 === length)) bytes.push(0xEF, 0xBF, 0xBD);
else lead = c;
continue;
}
} else if (lead) {
bytes.push(0xEF, 0xBF, 0xBD);
lead = null;
}
if (c < 0x80) bytes.push(c);
else if (c < 0x800) bytes.push(c >> 0x6 | 0xC0, c & 0x3F | 0x80);
else if (c < 0x10000) bytes.push(c >> 0xC | 0xE0, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80);
else bytes.push(c >> 0x12 | 0xF0, c >> 0xC & 0x3F | 0x80, c >> 0x6 & 0x3F | 0x80, c & 0x3F | 0x80);
}
return bytes;
}
},{"ieee754":112}],111:[function(require,module,exports){
(function (global){
'use strict';
module.exports = Pbf;
var Buffer = global.Buffer || require('./buffer');
function Pbf(buf) {
this.buf = !Buffer.isBuffer(buf) ? new Buffer(buf || 0) : buf;
this.pos = 0;
this.length = this.buf.length;
}
Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32,
POW_2_63 = Math.pow(2, 63);
Pbf.prototype = {
destroy: function() {
this.buf = null;
},
// === READING =================================================================
readFields: function(readField, result, end) {
end = end || this.length;
while (this.pos < end) {
var val = this.readVarint(),
tag = val >> 3,
startPos = this.pos;
readField(tag, result, this);
if (this.pos === startPos) this.skip(val);
}
return result;
},
readMessage: function(readField, result) {
return this.readFields(readField, result, this.readVarint() + this.pos);
},
readFixed32: function() {
var val = this.buf.readUInt32LE(this.pos);
this.pos += 4;
return val;
},
readSFixed32: function() {
var val = this.buf.readInt32LE(this.pos);
this.pos += 4;
return val;
},
// 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
readFixed64: function() {
var val = this.buf.readUInt32LE(this.pos) + this.buf.readUInt32LE(this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readSFixed64: function() {
var val = this.buf.readUInt32LE(this.pos) + this.buf.readInt32LE(this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readFloat: function() {
var val = this.buf.readFloatLE(this.pos);
this.pos += 4;
return val;
},
readDouble: function() {
var val = this.buf.readDoubleLE(this.pos);
this.pos += 8;
return val;
},
readVarint: function() {
var buf = this.buf,
val, b, b0, b1, b2, b3;
b0 = buf[this.pos++]; if (b0 < 0x80) return b0; b0 = b0 & 0x7f;
b1 = buf[this.pos++]; if (b1 < 0x80) return b0 | b1 << 7; b1 = (b1 & 0x7f) << 7;
b2 = buf[this.pos++]; if (b2 < 0x80) return b0 | b1 | b2 << 14; b2 = (b2 & 0x7f) << 14;
b3 = buf[this.pos++]; if (b3 < 0x80) return b0 | b1 | b2 | b3 << 21;
val = b0 | b1 | b2 | (b3 & 0x7f) << 21;
b = buf[this.pos++]; val += (b & 0x7f) * 0x10000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x800000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x40000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x2000000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x100000000000000; if (b < 0x80) return val;
b = buf[this.pos++]; val += (b & 0x7f) * 0x8000000000000000; if (b < 0x80) return val;
throw new Error('Expected varint not more than 10 bytes');
},
readVarint64: function() {
var startPos = this.pos,
val = this.readVarint();
if (val < POW_2_63) return val;
var pos = this.pos - 2;
while (this.buf[pos] === 0xff) pos--;
if (pos < startPos) pos = startPos;
val = 0;
for (var i = 0; i < pos - startPos + 1; i++) {
var b = ~this.buf[startPos + i] & 0x7f;
val += i < 4 ? b << i * 7 : b * Math.pow(2, i * 7);
}
return -val - 1;
},
readSVarint: function() {
var num = this.readVarint();
return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
},
readBoolean: function() {
return Boolean(this.readVarint());
},
readString: function() {
var end = this.readVarint() + this.pos,
str = this.buf.toString('utf8', this.pos, end);
this.pos = end;
return str;
},
readBytes: function() {
var end = this.readVarint() + this.pos,
buffer = this.buf.slice(this.pos, end);
this.pos = end;
return buffer;
},
// verbose for performance reasons; doesn't affect gzipped size
readPackedVarint: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readVarint());
return arr;
},
readPackedSVarint: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSVarint());
return arr;
},
readPackedBoolean: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readBoolean());
return arr;
},
readPackedFloat: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFloat());
return arr;
},
readPackedDouble: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readDouble());
return arr;
},
readPackedFixed32: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFixed32());
return arr;
},
readPackedSFixed32: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSFixed32());
return arr;
},
readPackedFixed64: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readFixed64());
return arr;
},
readPackedSFixed64: function() {
var end = this.readVarint() + this.pos, arr = [];
while (this.pos < end) arr.push(this.readSFixed64());
return arr;
},
skip: function(val) {
var type = val & 0x7;
if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {}
else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;
else if (type === Pbf.Fixed32) this.pos += 4;
else if (type === Pbf.Fixed64) this.pos += 8;
else throw new Error('Unimplemented type: ' + type);
},
// === WRITING =================================================================
writeTag: function(tag, type) {
this.writeVarint((tag << 3) | type);
},
realloc: function(min) {
var length = this.length || 16;
while (length < this.pos + min) length *= 2;
if (length !== this.length) {
var buf = new Buffer(length);
this.buf.copy(buf);
this.buf = buf;
this.length = length;
}
},
finish: function() {
this.length = this.pos;
this.pos = 0;
return this.buf.slice(0, this.length);
},
writeFixed32: function(val) {
this.realloc(4);
this.buf.writeUInt32LE(val, this.pos);
this.pos += 4;
},
writeSFixed32: function(val) {
this.realloc(4);
this.buf.writeInt32LE(val, this.pos);
this.pos += 4;
},
writeFixed64: function(val) {
this.realloc(8);
this.buf.writeInt32LE(val & -1, this.pos);
this.buf.writeUInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeSFixed64: function(val) {
this.realloc(8);
this.buf.writeInt32LE(val & -1, this.pos);
this.buf.writeInt32LE(Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeVarint: function(val) {
val = +val;
if (val <= 0x7f) {
this.realloc(1);
this.buf[this.pos++] = val;
} else if (val <= 0x3fff) {
this.realloc(2);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f);
} else if (val <= 0x1fffff) {
this.realloc(3);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 14) & 0x7f);
} else if (val <= 0xfffffff) {
this.realloc(4);
this.buf[this.pos++] = ((val >>> 0) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 7) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 14) & 0x7f) | 0x80;
this.buf[this.pos++] = ((val >>> 21) & 0x7f);
} else {
var pos = this.pos;
while (val >= 0x80) {
this.realloc(1);
this.buf[this.pos++] = (val & 0xff) | 0x80;
val /= 0x80;
}
this.realloc(1);
this.buf[this.pos++] = val | 0;
if (this.pos - pos > 10) throw new Error('Given varint doesn\'t fit into 10 bytes');
}
},
writeSVarint: function(val) {
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
},
writeBoolean: function(val) {
this.writeVarint(Boolean(val));
},
writeString: function(str) {
str = String(str);
var bytes = Buffer.byteLength(str);
this.writeVarint(bytes);
this.realloc(bytes);
this.buf.write(str, this.pos);
this.pos += bytes;
},
writeFloat: function(val) {
this.realloc(4);
this.buf.writeFloatLE(val, this.pos);
this.pos += 4;
},
writeDouble: function(val) {
this.realloc(8);
this.buf.writeDoubleLE(val, this.pos);
this.pos += 8;
},
writeBytes: function(buffer) {
var len = buffer.length;
this.writeVarint(len);
this.realloc(len);
for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
},
writeMessage: function(tag, fn, obj) {
this.writeTag(tag, Pbf.Bytes);
this.pos++; // reserve 1 byte for short message length
// write the message directly to the buffer and see how much was written
var startPos = this.pos;
fn(obj, this);
var len = this.pos - startPos;
var varintLen =
len <= 0x7f ? 1 :
len <= 0x3fff ? 2 :
len <= 0x1fffff ? 3 :
len <= 0xfffffff ? 4 : Math.ceil(Math.log(len) / (Math.LN2 * 7));
// if 1 byte isn't enough for encoding message length, shift the data to the right
if (varintLen > 1) {
this.realloc(varintLen - 1);
for (var i = this.pos - 1; i >= startPos; i--) this.buf[i + varintLen - 1] = this.buf[i];
}
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
},
writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); },
writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); },
writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); },
writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); },
writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); },
writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); },
writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); },
writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); },
writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); },
writeBytesField: function(tag, buffer) {
this.writeTag(tag, Pbf.Bytes);
this.writeBytes(buffer);
},
writeFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFixed32(val);
},
writeSFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeSFixed32(val);
},
writeFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeFixed64(val);
},
writeSFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeSFixed64(val);
},
writeVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeVarint(val);
},
writeSVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeSVarint(val);
},
writeStringField: function(tag, str) {
this.writeTag(tag, Pbf.Bytes);
this.writeString(str);
},
writeFloatField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFloat(val);
},
writeDoubleField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeDouble(val);
},
writeBooleanField: function(tag, val) {
this.writeVarintField(tag, Boolean(val));
}
};
function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]); }
function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]); }
function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]); }
function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]); }
function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]); }
function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]); }
function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); }
function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]); }
function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./buffer":110}],112:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isLE ? (nBytes - 1) : 0,
d = isLE ? -1 : 1,
s = buffer[offset + i]
i += d
e = s & ((1 << (-nBits)) - 1)
s >>= (-nBits)
nBits += eLen
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
m = e & ((1 << (-nBits)) - 1)
e >>= (-nBits)
nBits += mLen
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
if (e === 0) {
e = 1 - eBias
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity)
} else {
m = m + Math.pow(2, mLen)
e = e - eBias
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isLE ? 0 : (nBytes - 1),
d = isLE ? 1 : -1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
value = Math.abs(value)
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0
e = eMax
} else {
e = Math.floor(Math.log(value) / Math.LN2)
if (value * (c = Math.pow(2, -e)) < 1) {
e--
c *= 2
}
if (e + eBias >= 1) {
value += rt / c
} else {
value += rt * Math.pow(2, 1 - eBias)
}
if (value * c >= 2) {
e++
c /= 2
}
if (e + eBias >= eMax) {
m = 0
e = eMax
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen)
e = e + eBias
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
e = 0
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
e = (e << mLen) | m
eLen += mLen
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
buffer[offset + i - d] |= s * 128
}
},{}],113:[function(require,module,exports){
'use strict';
module.exports = Point;
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
clone: function() { return new Point(this.x, this.y); },
add: function(p) { return this.clone()._add(p); },
sub: function(p) { return this.clone()._sub(p); },
mult: function(k) { return this.clone()._mult(k); },
div: function(k) { return this.clone()._div(k); },
rotate: function(a) { return this.clone()._rotate(a); },
matMult: function(m) { return this.clone()._matMult(m); },
unit: function() { return this.clone()._unit(); },
perp: function() { return this.clone()._perp(); },
round: function() { return this.clone()._round(); },
mag: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
equals: function(p) {
return this.x === p.x &&
this.y === p.y;
},
dist: function(p) {
return Math.sqrt(this.distSqr(p));
},
distSqr: function(p) {
var dx = p.x - this.x,
dy = p.y - this.y;
return dx * dx + dy * dy;
},
angle: function() {
return Math.atan2(this.y, this.x);
},
angleTo: function(b) {
return Math.atan2(this.y - b.y, this.x - b.x);
},
angleWith: function(b) {
return this.angleWithSep(b.x, b.y);
},
// Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(θ) for θ.
angleWithSep: function(x, y) {
return Math.atan2(
this.x * y - this.y * x,
this.x * x + this.y * y);
},
_matMult: function(m) {
var x = m[0] * this.x + m[1] * this.y,
y = m[2] * this.x + m[3] * this.y;
this.x = x;
this.y = y;
return this;
},
_add: function(p) {
this.x += p.x;
this.y += p.y;
return this;
},
_sub: function(p) {
this.x -= p.x;
this.y -= p.y;
return this;
},
_mult: function(k) {
this.x *= k;
this.y *= k;
return this;
},
_div: function(k) {
this.x /= k;
this.y /= k;
return this;
},
_unit: function() {
this._div(this.mag());
return this;
},
_perp: function() {
var y = this.y;
this.y = this.x;
this.x = -y;
return this;
},
_rotate: function(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = cos * this.x - sin * this.y,
y = sin * this.x + cos * this.y;
this.x = x;
this.y = y;
return this;
},
_round: function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
}
};
// constructs Point from an array if necessary
Point.convert = function (a) {
if (a instanceof Point) {
return a;
}
if (Array.isArray(a)) {
return new Point(a[0], a[1]);
}
return a;
};
},{}],114:[function(require,module,exports){
/*
(c) 2013, Vladimir Agafonkin
RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
https://github.com/mourner/rbush
*/
(function () { 'use strict';
function rbush(maxEntries, format) {
// jshint newcap: false, validthis: true
if (!(this instanceof rbush)) return new rbush(maxEntries, format);
// max entries in a node is 9 by default; min node fill is 40% for best performance
this._maxEntries = Math.max(4, maxEntries || 9);
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
if (format) {
this._initFormat(format);
}
this.clear();
}
rbush.prototype = {
all: function () {
return this._all(this.data, []);
},
search: function (bbox) {
var node = this.data,
result = [],
toBBox = this.toBBox;
if (!intersects(bbox, node.bbox)) return result;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child.bbox;
if (intersects(bbox, childBBox)) {
if (node.leaf) result.push(child);
else if (contains(bbox, childBBox)) this._all(child, result);
else nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return result;
},
collides: function (bbox) {
var node = this.data,
toBBox = this.toBBox;
if (!intersects(bbox, node.bbox)) return false;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child.bbox;
if (intersects(bbox, childBBox)) {
if (node.leaf || contains(bbox, childBBox)) return true;
nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return false;
},
load: function (data) {
if (!(data && data.length)) return this;
if (data.length < this._minEntries) {
for (var i = 0, len = data.length; i < len; i++) {
this.insert(data[i]);
}
return this;
}
// recursively build the tree with the given data from stratch using OMT algorithm
var node = this._build(data.slice(), 0, data.length - 1, 0);
if (!this.data.children.length) {
// save as is if tree is empty
this.data = node;
} else if (this.data.height === node.height) {
// split root if trees have the same height
this._splitRoot(this.data, node);
} else {
if (this.data.height < node.height) {
// swap trees if inserted one is bigger
var tmpNode = this.data;
this.data = node;
node = tmpNode;
}
// insert the small tree into the large tree at appropriate level
this._insert(node, this.data.height - node.height - 1, true);
}
return this;
},
insert: function (item) {
if (item) this._insert(item, this.data.height - 1);
return this;
},
clear: function () {
this.data = {
children: [],
height: 1,
bbox: empty(),
leaf: true
};
return this;
},
remove: function (item) {
if (!item) return this;
var node = this.data,
bbox = this.toBBox(item),
path = [],
indexes = [],
i, parent, index, goingUp;
// depth-first iterative tree traversal
while (node || path.length) {
if (!node) { // go up
node = path.pop();
parent = path[path.length - 1];
i = indexes.pop();
goingUp = true;
}
if (node.leaf) { // check current node
index = node.children.indexOf(item);
if (index !== -1) {
// item found, remove the item and condense tree upwards
node.children.splice(index, 1);
path.push(node);
this._condense(path);
return this;
}
}
if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down
path.push(node);
indexes.push(i);
i = 0;
parent = node;
node = node.children[0];
} else if (parent) { // go right
i++;
node = parent.children[i];
goingUp = false;
} else node = null; // nothing found
}
return this;
},
toBBox: function (item) { return item; },
compareMinX: function (a, b) { return a[0] - b[0]; },
compareMinY: function (a, b) { return a[1] - b[1]; },
toJSON: function () { return this.data; },
fromJSON: function (data) {
this.data = data;
return this;
},
_all: function (node, result) {
var nodesToSearch = [];
while (node) {
if (node.leaf) result.push.apply(result, node.children);
else nodesToSearch.push.apply(nodesToSearch, node.children);
node = nodesToSearch.pop();
}
return result;
},
_build: function (items, left, right, height) {
var N = right - left + 1,
M = this._maxEntries,
node;
if (N <= M) {
// reached leaf level; return leaf
node = {
children: items.slice(left, right + 1),
height: 1,
bbox: null,
leaf: true
};
calcBBox(node, this.toBBox);
return node;
}
if (!height) {
// target height of the bulk-loaded tree
height = Math.ceil(Math.log(N) / Math.log(M));
// target number of root entries to maximize storage utilization
M = Math.ceil(N / Math.pow(M, height - 1));
}
// TODO eliminate recursion?
node = {
children: [],
height: height,
bbox: null
};
// split the items into M mostly square tiles
var N2 = Math.ceil(N / M),
N1 = N2 * Math.ceil(Math.sqrt(M)),
i, j, right2, right3;
multiSelect(items, left, right, N1, this.compareMinX);
for (i = left; i <= right; i += N1) {
right2 = Math.min(i + N1 - 1, right);
multiSelect(items, i, right2, N2, this.compareMinY);
for (j = i; j <= right2; j += N2) {
right3 = Math.min(j + N2 - 1, right2);
// pack each entry recursively
node.children.push(this._build(items, j, right3, height - 1));
}
}
calcBBox(node, this.toBBox);
return node;
},
_chooseSubtree: function (bbox, node, level, path) {
var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
while (true) {
path.push(node);
if (node.leaf || path.length - 1 === level) break;
minArea = minEnlargement = Infinity;
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
area = bboxArea(child.bbox);
enlargement = enlargedArea(bbox, child.bbox) - area;
// choose entry with the least area enlargement
if (enlargement < minEnlargement) {
minEnlargement = enlargement;
minArea = area < minArea ? area : minArea;
targetNode = child;
} else if (enlargement === minEnlargement) {
// otherwise choose one with the smallest area
if (area < minArea) {
minArea = area;
targetNode = child;
}
}
}
node = targetNode;
}
return node;
},
_insert: function (item, level, isNode) {
var toBBox = this.toBBox,
bbox = isNode ? item.bbox : toBBox(item),
insertPath = [];
// find the best node for accommodating the item, saving all nodes along the path too
var node = this._chooseSubtree(bbox, this.data, level, insertPath);
// put the item into the node
node.children.push(item);
extend(node.bbox, bbox);
// split on node overflow; propagate upwards if necessary
while (level >= 0) {
if (insertPath[level].children.length > this._maxEntries) {
this._split(insertPath, level);
level--;
} else break;
}
// adjust bboxes along the insertion path
this._adjustParentBBoxes(bbox, insertPath, level);
},
// split overflowed node into two
_split: function (insertPath, level) {
var node = insertPath[level],
M = node.children.length,
m = this._minEntries;
this._chooseSplitAxis(node, m, M);
var newNode = {
children: node.children.splice(this._chooseSplitIndex(node, m, M)),
height: node.height
};
if (node.leaf) newNode.leaf = true;
calcBBox(node, this.toBBox);
calcBBox(newNode, this.toBBox);
if (level) insertPath[level - 1].children.push(newNode);
else this._splitRoot(node, newNode);
},
_splitRoot: function (node, newNode) {
// split root node
this.data = {
children: [node, newNode],
height: node.height + 1
};
calcBBox(this.data, this.toBBox);
},
_chooseSplitIndex: function (node, m, M) {
var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
minOverlap = minArea = Infinity;
for (i = m; i <= M - m; i++) {
bbox1 = distBBox(node, 0, i, this.toBBox);
bbox2 = distBBox(node, i, M, this.toBBox);
overlap = intersectionArea(bbox1, bbox2);
area = bboxArea(bbox1) + bboxArea(bbox2);
// choose distribution with minimum overlap
if (overlap < minOverlap) {
minOverlap = overlap;
index = i;
minArea = area < minArea ? area : minArea;
} else if (overlap === minOverlap) {
// otherwise choose distribution with minimum area
if (area < minArea) {
minArea = area;
index = i;
}
}
}
return index;
},
// sorts node children by the best axis for split
_chooseSplitAxis: function (node, m, M) {
var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
xMargin = this._allDistMargin(node, m, M, compareMinX),
yMargin = this._allDistMargin(node, m, M, compareMinY);
// if total distributions margin value is minimal for x, sort by minX,
// otherwise it's already sorted by minY
if (xMargin < yMargin) node.children.sort(compareMinX);
},
// total margin of all possible split distributions where each node is at least m full
_allDistMargin: function (node, m, M, compare) {
node.children.sort(compare);
var toBBox = this.toBBox,
leftBBox = distBBox(node, 0, m, toBBox),
rightBBox = distBBox(node, M - m, M, toBBox),
margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
i, child;
for (i = m; i < M - m; i++) {
child = node.children[i];
extend(leftBBox, node.leaf ? toBBox(child) : child.bbox);
margin += bboxMargin(leftBBox);
}
for (i = M - m - 1; i >= m; i--) {
child = node.children[i];
extend(rightBBox, node.leaf ? toBBox(child) : child.bbox);
margin += bboxMargin(rightBBox);
}
return margin;
},
_adjustParentBBoxes: function (bbox, path, level) {
// adjust bboxes along the given tree path
for (var i = level; i >= 0; i--) {
extend(path[i].bbox, bbox);
}
},
_condense: function (path) {
// go through the path, removing empty nodes and updating bboxes
for (var i = path.length - 1, siblings; i >= 0; i--) {
if (path[i].children.length === 0) {
if (i > 0) {
siblings = path[i - 1].children;
siblings.splice(siblings.indexOf(path[i]), 1);
} else this.clear();
} else calcBBox(path[i], this.toBBox);
}
},
_initFormat: function (format) {
// data format (minX, minY, maxX, maxY accessors)
// uses eval-type function compilation instead of just accepting a toBBox function
// because the algorithms are very sensitive to sorting functions performance,
// so they should be dead simple and without inner calls
// jshint evil: true
var compareArr = ['return a', ' - b', ';'];
this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
}
};
// calculate node's bbox from bboxes of its children
function calcBBox(node, toBBox) {
node.bbox = distBBox(node, 0, node.children.length, toBBox);
}
// min bounding rectangle of node children from k to p-1
function distBBox(node, k, p, toBBox) {
var bbox = empty();
for (var i = k, child; i < p; i++) {
child = node.children[i];
extend(bbox, node.leaf ? toBBox(child) : child.bbox);
}
return bbox;
}
function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; }
function extend(a, b) {
a[0] = Math.min(a[0], b[0]);
a[1] = Math.min(a[1], b[1]);
a[2] = Math.max(a[2], b[2]);
a[3] = Math.max(a[3], b[3]);
return a;
}
function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; }
function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; }
function bboxArea(a) { return (a[2] - a[0]) * (a[3] - a[1]); }
function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); }
function enlargedArea(a, b) {
return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
(Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
}
function intersectionArea(a, b) {
var minX = Math.max(a[0], b[0]),
minY = Math.max(a[1], b[1]),
maxX = Math.min(a[2], b[2]),
maxY = Math.min(a[3], b[3]);
return Math.max(0, maxX - minX) *
Math.max(0, maxY - minY);
}
function contains(a, b) {
return a[0] <= b[0] &&
a[1] <= b[1] &&
b[2] <= a[2] &&
b[3] <= a[3];
}
function intersects(a, b) {
return b[0] <= a[2] &&
b[1] <= a[3] &&
b[2] >= a[0] &&
b[3] >= a[1];
}
// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
// combines selection algorithm with binary divide & conquer approach
function multiSelect(arr, left, right, n, compare) {
var stack = [left, right],
mid;
while (stack.length) {
right = stack.pop();
left = stack.pop();
if (right - left <= n) continue;
mid = left + Math.ceil((right - left) / n / 2) * n;
select(arr, left, right, mid, compare);
stack.push(left, mid, mid, right);
}
}
// Floyd-Rivest selection algorithm:
// sort an array between left and right (inclusive) so that the smallest k elements come first (unordered)
function select(arr, left, right, k, compare) {
var n, i, z, s, sd, newLeft, newRight, t, j;
while (right > left) {
if (right - left > 600) {
n = right - left + 1;
i = k - left + 1;
z = Math.log(n);
s = 0.5 * Math.exp(2 * z / 3);
sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1);
newLeft = Math.max(left, Math.floor(k - i * s / n + sd));
newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd));
select(arr, newLeft, newRight, k, compare);
}
t = arr[k];
i = left;
j = right;
swap(arr, left, k);
if (compare(arr[right], t) > 0) swap(arr, left, right);
while (i < j) {
swap(arr, i, j);
i++;
j--;
while (compare(arr[i], t) < 0) i++;
while (compare(arr[j], t) > 0) j--;
}
if (compare(arr[left], t) === 0) swap(arr, left, j);
else {
j++;
swap(arr, j, right);
}
if (j <= k) left = j + 1;
if (k <= j) right = j - 1;
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// export as AMD/CommonJS module or global variable
if (typeof define === 'function' && define.amd) define('rbush', function() { return rbush; });
else if (typeof module !== 'undefined') module.exports = rbush;
else if (typeof self !== 'undefined') self.rbush = rbush;
else window.rbush = rbush;
})();
},{}],115:[function(require,module,exports){
// Copyright 2014 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
void (function(root, factory) {
if (typeof define === "function" && define.amd) {
define(factory)
} else if (typeof exports === "object") {
module.exports = factory()
} else {
root.resolveUrl = factory()
}
}(this, function() {
function resolveUrl(/* ...urls */) {
var numUrls = arguments.length
if (numUrls === 0) {
throw new Error("resolveUrl requires at least one argument; got none.")
}
var base = document.createElement("base")
base.href = arguments[0]
if (numUrls === 1) {
return base.href
}
var head = document.getElementsByTagName("head")[0]
head.insertBefore(base, head.firstChild)
var a = document.createElement("a")
var resolved
for (var index = 1; index < numUrls; index++) {
a.href = arguments[index]
resolved = a.href
base.href = resolved
}
head.removeChild(base)
return resolved
}
return resolveUrl
}));
},{}],116:[function(require,module,exports){
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Ported from Webkit
* http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h
*/
module.exports = UnitBezier;
function UnitBezier(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p2y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier.prototype.sampleCurveX = function(t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
};
UnitBezier.prototype.sampleCurveY = function(t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
};
UnitBezier.prototype.sampleCurveDerivativeX = function(t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
};
UnitBezier.prototype.solveCurveX = function(x, epsilon) {
if (typeof epsilon === 'undefined') epsilon = 1e-6;
var t0, t1, t2, x2, i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++) {
x2 = this.sampleCurveX(t2) - x;
if (Math.abs(x2) < epsilon) return t2;
var d2 = this.sampleCurveDerivativeX(t2);
if (Math.abs(d2) < 1e-6) break;
t2 = t2 - x2 / d2;
}
// Fall back to the bisection method for reliability.
t0 = 0.0;
t1 = 1.0;
t2 = x;
if (t2 < t0) return t0;
if (t2 > t1) return t1;
while (t0 < t1) {
x2 = this.sampleCurveX(t2);
if (Math.abs(x2 - x) < epsilon) return t2;
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
// Failure.
return t2;
};
UnitBezier.prototype.solve = function(x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
};
},{}],117:[function(require,module,exports){
module.exports.VectorTile = require('./lib/vectortile.js');
module.exports.VectorTileFeature = require('./lib/vectortilefeature.js');
module.exports.VectorTileLayer = require('./lib/vectortilelayer.js');
},{"./lib/vectortile.js":118,"./lib/vectortilefeature.js":119,"./lib/vectortilelayer.js":120}],118:[function(require,module,exports){
'use strict';
var VectorTileLayer = require('./vectortilelayer');
module.exports = VectorTile;
function VectorTile(pbf, end) {
this.layers = pbf.readFields(readTile, {}, end);
}
function readTile(tag, layers, pbf) {
if (tag === 3) {
var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
if (layer.length) layers[layer.name] = layer;
}
}
},{"./vectortilelayer":120}],119:[function(require,module,exports){
'use strict';
var Point = require('point-geometry');
module.exports = VectorTileFeature;
function VectorTileFeature(pbf, end, extent, keys, values) {
// Public
this.properties = {};
this.extent = extent;
this.type = 0;
// Private
this._pbf = pbf;
this._geometry = -1;
this._keys = keys;
this._values = values;
pbf.readFields(readFeature, this, end);
}
function readFeature(tag, feature, pbf) {
if (tag == 1) feature._id = pbf.readVarint();
else if (tag == 2) readTag(pbf, feature);
else if (tag == 3) feature.type = pbf.readVarint();
else if (tag == 4) feature._geometry = pbf.pos;
}
function readTag(pbf, feature) {
var end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var key = feature._keys[pbf.readVarint()],
value = feature._values[pbf.readVarint()];
feature.properties[key] = value;
}
}
VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
VectorTileFeature.prototype.loadGeometry = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
lines = [],
line;
while (pbf.pos < end) {
if (!length) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (cmd === 1) { // moveTo
if (line) lines.push(line);
line = [];
}
line.push(new Point(x, y));
} else if (cmd === 7) {
line.push(line[0].clone()); // closePolygon
} else {
throw new Error('unknown command ' + cmd);
}
}
if (line) lines.push(line);
return lines;
};
VectorTileFeature.prototype.bbox = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
x1 = Infinity,
x2 = -Infinity,
y1 = Infinity,
y2 = -Infinity;
while (pbf.pos < end) {
if (!length) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
} else if (cmd !== 7) {
throw new Error('unknown command ' + cmd);
}
}
return [x1, y1, x2, y2];
};
VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
var size = this.extent * Math.pow(2, z),
x0 = this.extent * x,
y0 = this.extent * y,
coords = this.loadGeometry(),
type = VectorTileFeature.types[this.type];
for (var i = 0; i < coords.length; i++) {
var line = coords[i];
for (var j = 0; j < line.length; j++) {
var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
line[j] = [
(p.x + x0) * 360 / size - 180,
360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90
];
}
}
if (type === 'Point' && coords.length === 1) {
coords = coords[0][0];
} else if (type === 'Point') {
coords = coords[0];
type = 'MultiPoint';
} else if (type === 'LineString' && coords.length === 1) {
coords = coords[0];
} else if (type === 'LineString') {
type = 'MultiLineString';
}
return {
type: "Feature",
geometry: {
type: type,
coordinates: coords
},
properties: this.properties
};
};
},{"point-geometry":113}],120:[function(require,module,exports){
'use strict';
var VectorTileFeature = require('./vectortilefeature.js');
module.exports = VectorTileLayer;
function VectorTileLayer(pbf, end) {
// Public
this.version = 1;
this.name = null;
this.extent = 4096;
this.length = 0;
// Private
this._pbf = pbf;
this._keys = [];
this._values = [];
this._features = [];
pbf.readFields(readLayer, this, end);
this.length = this._features.length;
}
function readLayer(tag, layer, pbf) {
if (tag === 15) layer.version = pbf.readVarint();
else if (tag === 1) layer.name = pbf.readString();
else if (tag === 5) layer.extent = pbf.readVarint();
else if (tag === 2) layer._features.push(pbf.pos);
else if (tag === 3) layer._keys.push(pbf.readString());
else if (tag === 4) layer._values.push(readValueMessage(pbf));
}
function readValueMessage(pbf) {
var value = null,
end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var tag = pbf.readVarint() >> 3;
value = tag === 1 ? pbf.readString() :
tag === 2 ? pbf.readFloat() :
tag === 3 ? pbf.readDouble() :
tag === 4 ? pbf.readVarint64() :
tag === 5 ? pbf.readVarint() :
tag === 6 ? pbf.readSVarint() :
tag === 7 ? pbf.readBoolean() : null;
}
return value;
}
// return feature `i` from this layer as a `VectorTileFeature`
VectorTileLayer.prototype.feature = function(i) {
if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
this._pbf.pos = this._features[i];
var end = this._pbf.readVarint() + this._pbf.pos;
return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
};
},{"./vectortilefeature.js":119}],121:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],122:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
currentQueue[queueIndex].run();
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],123:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],124:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":123,"_process":122,"inherits":121}],125:[function(require,module,exports){
var bundleFn = arguments[3];
var sources = arguments[4];
var cache = arguments[5];
var stringify = JSON.stringify;
module.exports = function (fn) {
var keys = [];
var wkey;
var cacheKeys = Object.keys(cache);
for (var i = 0, l = cacheKeys.length; i < l; i++) {
var key = cacheKeys[i];
if (cache[key].exports === fn) {
wkey = key;
break;
}
}
if (!wkey) {
wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
var wcache = {};
for (var i = 0, l = cacheKeys.length; i < l; i++) {
var key = cacheKeys[i];
wcache[key] = key;
}
sources[wkey] = [
Function(['require','module','exports'], '(' + fn + ')(self)'),
wcache
];
}
var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
var scache = {}; scache[wkey] = wkey;
sources[skey] = [
Function(['require'],'require(' + stringify(wkey) + ')(self)'),
scache
];
var src = '(' + bundleFn + ')({'
+ Object.keys(sources).map(function (key) {
return stringify(key) + ':['
+ sources[key][0]
+ ',' + stringify(sources[key][1]) + ']'
;
}).join(',')
+ '},{},[' + stringify(skey) + '])'
;
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
return new Worker(URL.createObjectURL(
new Blob([src], { type: 'text/javascript' })
));
};
},{}]},{},[22])(22)
});
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvYnVmZmVyX3NldC5qcyIsImpzL2RhdGEvYnVmZmVyL2NvbGxpc2lvbl9ib3hfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2ZpbGxfdmVydGV4X2J1ZmZlci5qcyIsImpzL2RhdGEvYnVmZmVyL2dseXBoX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9pY29uX3ZlcnRleF9idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci9saW5lX2VsZW1lbnRfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvbGluZV92ZXJ0ZXhfYnVmZmVyLmpzIiwianMvZGF0YS9idWZmZXIvb3V0bGluZV9lbGVtZW50c19idWZmZXIuanMiLCJqcy9kYXRhL2J1ZmZlci90cmlhbmdsZV9lbGVtZW50X2J1ZmZlci5qcyIsImpzL2RhdGEvY3JlYXRlX2J1Y2tldC5qcyIsImpzL2RhdGEvZWxlbWVudF9ncm91cHMuanMiLCJqcy9kYXRhL2ZlYXR1cmVfdHJlZS5qcyIsImpzL2RhdGEvZmlsbF9idWNrZXQuanMiLCJqcy9kYXRhL2xpbmVfYnVja2V0LmpzIiwianMvZGF0YS9zeW1ib2xfYnVja2V0LmpzIiwianMvZ2VvL2Nvb3JkaW5hdGUuanMiLCJqcy9nZW8vbGF0X2xuZy5qcyIsImpzL2dlby9sYXRfbG5nX2JvdW5kcy5qcyIsImpzL2dlby90cmFuc2Zvcm0uanMiLCJqcy9saWIvZGVidWd0ZXh0LmpzIiwianMvbWFwYm94LWdsLmpzIiwianMvcmVuZGVyL2RyYXdfYmFja2dyb3VuZC5qcyIsImpzL3JlbmRlci9kcmF3X2NvbGxpc2lvbl9kZWJ1Zy5qcyIsImpzL3JlbmRlci9kcmF3X2RlYnVnLmpzIiwianMvcmVuZGVyL2RyYXdfZmlsbC5qcyIsImpzL3JlbmRlci9kcmF3X2xpbmUuanMiLCJqcy9yZW5kZXIvZHJhd19yYXN0ZXIuanMiLCJqcy9yZW5kZXIvZHJhd19zeW1ib2wuanMiLCJqcy9yZW5kZXIvZHJhd192ZXJ0aWNlcy5qcyIsImpzL3JlbmRlci9mcmFtZV9oaXN0b3J5LmpzIiwianMvcmVuZGVyL2dsX3V0aWwuanMiLCJqcy9yZW5kZXIvbGluZV9hdGxhcy5qcyIsImpzL3JlbmRlci9wYWludGVyLmpzIiwianMvcmVuZGVyL3NoYWRlcnMuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl9zb3VyY2UuanMiLCJqcy9zb3VyY2UvZ2VvanNvbl93cmFwcGVyLmpzIiwianMvc291cmNlL3Jhc3Rlcl90aWxlX3NvdXJjZS5qcyIsImpzL3NvdXJjZS9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdGlsZS5qcyIsImpzL3NvdXJjZS90aWxlX2Nvb3JkLmpzIiwianMvc291cmNlL3RpbGVfcHlyYW1pZC5qcyIsImpzL3NvdXJjZS92ZWN0b3JfdGlsZV9zb3VyY2UuanMiLCJqcy9zb3VyY2UvdmlkZW9fc291cmNlLmpzIiwianMvc291cmNlL3dvcmtlci5qcyIsImpzL3NvdXJjZS93b3JrZXJfdGlsZS5qcyIsImpzL3N0eWxlL2FuaW1hdGlvbl9sb29wLmpzIiwianMvc3R5bGUvaW1hZ2Vfc3ByaXRlLmpzIiwianMvc3R5bGUvbGF5b3V0X3Byb3BlcnRpZXMuanMiLCJqcy9zdHlsZS9wYWludF9wcm9wZXJ0aWVzLmpzIiwianMvc3R5bGUvcmVmZXJlbmNlLmpzIiwianMvc3R5bGUvc3R5bGUuanMiLCJqcy9zdHlsZS9zdHlsZV9jb25zdGFudC5qcyIsImpzL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uLmpzIiwianMvc3R5bGUvc3R5bGVfZGVjbGFyYXRpb25fc2V0LmpzIiwianMvc3R5bGUvc3R5bGVfbGF5ZXIuanMiLCJqcy9zdHlsZS9zdHlsZV90cmFuc2l0aW9uLmpzIiwianMvc3ltYm9sL2FuY2hvci5qcyIsImpzL3N5bWJvbC9iaW5fcGFjay5qcyIsImpzL3N5bWJvbC9jaGVja19tYXhfYW5nbGUuanMiLCJqcy9zeW1ib2wvY2xpcF9saW5lLmpzIiwianMvc3ltYm9sL2NvbGxpc2lvbl9ib3guanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX2ZlYXR1cmUuanMiLCJqcy9zeW1ib2wvY29sbGlzaW9uX3RpbGUuanMiLCJqcy9zeW1ib2wvZ2V0X2FuY2hvcnMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfYXRsYXMuanMiLCJqcy9zeW1ib2wvZ2x5cGhfc291cmNlLmpzIiwianMvc3ltYm9sL21lcmdlbGluZXMuanMiLCJqcy9zeW1ib2wvcXVhZHMuanMiLCJqcy9zeW1ib2wvcmVzb2x2ZV9pY29ucy5qcyIsImpzL3N5bWJvbC9yZXNvbHZlX3RleHQuanMiLCJqcy9zeW1ib2wvc2hhcGluZy5qcyIsImpzL3N5bWJvbC9zcHJpdGVfYXRsYXMuanMiLCJqcy91aS9jYW1lcmEuanMiLCJqcy91aS9jb250cm9sL2F0dHJpYnV0aW9uLmpzIiwianMvdWkvY29udHJvbC9jb250cm9sLmpzIiwianMvdWkvY29udHJvbC9uYXZpZ2F0aW9uLmpzIiwianMvdWkvaGFuZGxlcnMuanMiLCJqcy91aS9oYXNoLmpzIiwianMvdWkvaW50ZXJhY3Rpb24uanMiLCJqcy91aS9tYXAuanMiLCJqcy91aS9wb3B1cC5qcyIsImpzL3V0aWwvYWN0b3IuanMiLCJqcy91dGlsL2Jyb3dzZXIvYWpheC5qcyIsImpzL3V0aWwvYnJvd3Nlci9icm93c2VyLmpzIiwianMvdXRpbC9icm93c2VyL2NhbnZhcy5qcyIsImpzL3V0aWwvYnJvd3Nlci9kaXNwYXRjaGVyLmpzIiwianMvdXRpbC9icm93c2VyL2RvbS5qcyIsImpzL3V0aWwvY29uZmlnLmpzIiwianMvdXRpbC9ldmVudGVkLmpzIiwianMvdXRpbC9nbHlwaHMuanMiLCJqcy91dGlsL2ludGVycG9sYXRlLmpzIiwianMvdXRpbC9tYXBib3guanMiLCJqcy91dGlsL21ydV9jYWNoZS5qcyIsImpzL3V0aWwvdG9rZW4uanMiLCJqcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvY3NzY29sb3JwYXJzZXIvY3NzY29sb3JwYXJzZXIuanMiLCJub2RlX21vZHVsZXMvZmVhdHVyZS1maWx0ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZ2VvanNvbi12dC9zcmMvY2xpcC5qcyIsIm5vZGVfbW9kdWxlcy9nZW9qc29uLXZ0L3NyYy9jb252ZXJ0LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3NpbXBsaWZ5LmpzIiwibm9kZV9tb2R1bGVzL2dlb2pzb24tdnQvc3JjL3RpbGUuanMiLCJub2RlX21vZHVsZXMvZ2wtbWF0cml4L2Rpc3QvZ2wtbWF0cml4LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1mdW5jdGlvbi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9saWIvdmFsaWRhdGUvbGF0ZXN0LmpzIiwibm9kZV9tb2R1bGVzL21hcGJveC1nbC1zdHlsZS1zcGVjL2xpYi92YWxpZGF0ZS9wYXJzZWQuanMiLCJub2RlX21vZHVsZXMvbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdC5qcyIsIm5vZGVfbW9kdWxlcy9tYXBib3gtZ2wtc3R5bGUtc3BlYy9yZWZlcmVuY2UvdjcuanNvbiIsIm5vZGVfbW9kdWxlcy9wYmYvYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3BiZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYmYvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcG9pbnQtZ2VvbWV0cnkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcmJ1c2gvcmJ1c2guanMiLCJub2RlX21vZHVsZXMvcmVzb2x2ZS11cmwvcmVzb2x2ZS11cmwuanMiLCJub2RlX21vZHVsZXMvdW5pdGJlemllci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZS5qcyIsIm5vZGVfbW9kdWxlcy92ZWN0b3ItdGlsZS9saWIvdmVjdG9ydGlsZWZlYXR1cmUuanMiLCJub2RlX21vZHVsZXMvdmVjdG9yLXRpbGUvbGliL3ZlY3RvcnRpbGVsYXllci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy93YXRjaGlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJub2RlX21vZHVsZXMvd2Vid29ya2lmeS9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzb0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxdUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9UQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4cElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQy9KQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzFrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIndXNlIHN0cmljdCc7XG5cbi8vIGEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIGEgc2luZ2xlIGFycmF5YnVmZmVyXG5cbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyO1xuXG5mdW5jdGlvbiBCdWZmZXIoYnVmZmVyKSB7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgICAgdGhpcy5hcnJheSA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmRlZmF1bHRMZW5ndGgpO1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGVmYXVsdExlbmd0aDtcbiAgICAgICAgdGhpcy5zZXR1cFZpZXdzKCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBvbmx5IHJlY3JlYXRlIGJ1ZmZlcnMgYWZ0ZXIgcmVjZWl2aW5nIHRoZW0gZnJvbSB3b3JrZXJzIGZvciBiaW5kaW5nIHRvIGdsLFxuICAgICAgICAvLyBzbyB3ZSBvbmx5IG5lZWQgdGhlc2UgMiBwcm9wZXJ0aWVzXG4gICAgICAgIHRoaXMuYXJyYXkgPSBidWZmZXIuYXJyYXk7XG4gICAgICAgIHRoaXMucG9zID0gYnVmZmVyLnBvcztcbiAgICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUgPSB7XG4gICAgcG9zOiAwLFxuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBpbiBvbmUgaXRlbVxuICAgIGRlZmF1bHRMZW5ndGg6IDgxOTIsIC8vIGluaXRpYWwgYnVmZmVyIHNpemVcbiAgICBhcnJheVR5cGU6ICdBUlJBWV9CVUZGRVInLCAvLyBnbCBidWZmZXIgdHlwZVxuXG4gICAgZ2V0IGluZGV4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3MgLyB0aGlzLml0ZW1TaXplO1xuICAgIH0sXG5cbiAgICBzZXR1cFZpZXdzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gc2V0IHVwIHZpZXdzIGZvciBlYWNoIHR5cGUgdG8gYWRkIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzIHRvIHRoZSBzYW1lIGJ1ZmZlclxuICAgICAgICB0aGlzLnVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLmJ5dGVzID0gbmV3IEludDhBcnJheSh0aGlzLmFycmF5KTtcbiAgICAgICAgdGhpcy51c2hvcnRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICB0aGlzLnNob3J0cyA9IG5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXkpO1xuICAgIH0sXG5cbiAgICAvLyBiaW5kcyB0aGUgYnVmZmVyIHRvIGEgd2ViZ2wgY29udGV4dFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsKSB7XG4gICAgICAgIHZhciB0eXBlID0gZ2xbdGhpcy5hcnJheVR5cGVdO1xuICAgICAgICBpZiAoIXRoaXMuYnVmZmVyKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICAgICAgZ2wuYmluZEJ1ZmZlcih0eXBlLCB0aGlzLmJ1ZmZlcik7XG4gICAgICAgICAgICBnbC5idWZmZXJEYXRhKHR5cGUsIHRoaXMuYXJyYXkuc2xpY2UoMCwgdGhpcy5wb3MpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgICAgIC8vIGR1bXAgYXJyYXkgYnVmZmVyIG9uY2UgaXQncyBib3VuZCB0byBnbFxuICAgICAgICAgICAgdGhpcy5hcnJheSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC5iaW5kQnVmZmVyKHR5cGUsIHRoaXMuYnVmZmVyKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBkZXN0cm95OiBmdW5jdGlvbihnbCkge1xuICAgICAgICBpZiAodGhpcy5idWZmZXIpIHtcbiAgICAgICAgICAgIGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gaW5jcmVhc2UgdGhlIGJ1ZmZlciBzaXplIGJ5IDUwJSBpZiBhIG5ldyBpdGVtIGRvZXNuJ3QgZml0XG4gICAgcmVzaXplOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoIDwgdGhpcy5wb3MgKyB0aGlzLml0ZW1TaXplKSB7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmxlbmd0aCA8IHRoaXMucG9zICsgdGhpcy5pdGVtU2l6ZSkge1xuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlIHRoZSBsZW5ndGggYnkgNTAlIGJ1dCBrZWVwIGl0IGV2ZW5cbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IE1hdGgucm91bmQodGhpcy5sZW5ndGggKiAxLjUgLyAyKSAqIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGFycmF5IGJ1ZmZlcnMgY2FuJ3QgYmUgcmVzaXplZCwgc28gd2UgY3JlYXRlIGEgbmV3IG9uZSBhbmQgcmVzZXQgYWxsIGJ5dGVzIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5QnVmZmVyKHRoaXMubGVuZ3RoKTtcblxuICAgICAgICAgICAgdmFyIHVieXRlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXkpO1xuICAgICAgICAgICAgdWJ5dGVzLnNldCh0aGlzLnVieXRlcyk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dXBWaWV3cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExpbmVWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2xpbmVfdmVydGV4X2J1ZmZlcicpO1xudmFyIExpbmVFbGVtZW50QnVmZmVyID0gcmVxdWlyZSgnLi9saW5lX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgRmlsbFZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vZmlsbF92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgRmlsbEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgT3V0bGluZUVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL291dGxpbmVfZWxlbWVudHNfYnVmZmVyJyk7XG52YXIgR2x5cGhWZXJ0ZXhCdWZmZXIgPSByZXF1aXJlKCcuL2dseXBoX3ZlcnRleF9idWZmZXInKTtcbnZhciBHbHlwaEVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgSWNvblZlcnRleEJ1ZmZlciA9IHJlcXVpcmUoJy4vaWNvbl92ZXJ0ZXhfYnVmZmVyJyk7XG52YXIgSWNvbkVsZW1lbnRCdWZmZXIgPSByZXF1aXJlKCcuL3RyaWFuZ2xlX2VsZW1lbnRfYnVmZmVyJyk7XG52YXIgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyID0gcmVxdWlyZSgnLi9jb2xsaXNpb25fYm94X3ZlcnRleF9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihidWZmZXJzZXQpIHtcbiAgICBidWZmZXJzZXQgPSBidWZmZXJzZXQgfHwge307XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2x5cGhWZXJ0ZXg6IG5ldyBHbHlwaFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZ2x5cGhWZXJ0ZXgpLFxuICAgICAgICBnbHlwaEVsZW1lbnQ6IG5ldyBHbHlwaEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb25WZXJ0ZXg6IG5ldyBJY29uVmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5pY29uVmVydGV4KSxcbiAgICAgICAgaWNvbkVsZW1lbnQ6IG5ldyBJY29uRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQuaWNvbkVsZW1lbnQpLFxuICAgICAgICBmaWxsVmVydGV4OiBuZXcgRmlsbFZlcnRleEJ1ZmZlcihidWZmZXJzZXQuZmlsbFZlcnRleCksXG4gICAgICAgIGZpbGxFbGVtZW50OiBuZXcgRmlsbEVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmZpbGxFbGVtZW50KSxcbiAgICAgICAgb3V0bGluZUVsZW1lbnQ6IG5ldyBPdXRsaW5lRWxlbWVudEJ1ZmZlcihidWZmZXJzZXQub3V0bGluZUVsZW1lbnQpLFxuICAgICAgICBsaW5lVmVydGV4OiBuZXcgTGluZVZlcnRleEJ1ZmZlcihidWZmZXJzZXQubGluZVZlcnRleCksXG4gICAgICAgIGxpbmVFbGVtZW50OiBuZXcgTGluZUVsZW1lbnRCdWZmZXIoYnVmZmVyc2V0LmxpbmVFbGVtZW50KSxcbiAgICAgICAgY29sbGlzaW9uQm94VmVydGV4OiBuZXcgQ29sbGlzaW9uQm94VmVydGV4QnVmZmVyKGJ1ZmZlcnNldC5jb2xsaXNpb25Cb3hWZXJ0ZXgpXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5Db2xsaXNpb25Cb3hWZXJ0ZXhCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiAxMiwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIGFkZDogZnVuY3Rpb24ocG9pbnQsIGV4dHJ1ZGUsIG1heFpvb20sIHBsYWNlbWVudFpvb20pIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXg7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSBwb2ludC54O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSBwb2ludC55O1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQoZXh0cnVkZS54KTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChleHRydWRlLnkpO1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSA9IE1hdGguZmxvb3IobWF4Wm9vbSAqIDEwKTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gPSBNYXRoLmZsb29yKHBsYWNlbWVudFpvb20gKiAxMCk7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gRmlsbFZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5GaWxsVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogNCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ID09IDQgYnl0ZXMpXG5cbiAgICBhZGQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgdmFyIHBvczIgPSB0aGlzLnBvcyAvIDI7XG5cbiAgICAgICAgdGhpcy5yZXNpemUoKTtcblxuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMF0gPSB4O1xuICAgICAgICB0aGlzLnNob3J0c1twb3MyICsgMV0gPSB5O1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaFZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gR2x5cGhWZXJ0ZXhCdWZmZXIoYnVmZmVyKSB7XG4gICAgQnVmZmVyLmNhbGwodGhpcywgYnVmZmVyKTtcbn1cblxuXG5HbHlwaFZlcnRleEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgZGVmYXVsdExlbmd0aDogMjA0OCAqIDE2LFxuICAgIGl0ZW1TaXplOiAxNixcblxuICAgIGFkZDogZnVuY3Rpb24oeCwgeSwgb3gsIG95LCB0eCwgdHksIG1pbnpvb20sIG1heHpvb20sIGxhYmVsbWluem9vbSkge1xuICAgICAgICB2YXIgcG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICBwb3MyID0gcG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IHg7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAxXSA9IHk7XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAyXSA9IE1hdGgucm91bmQob3ggKiA2NCk7IC8vIHVzZSAxLzY0IHBpeGVscyBmb3IgcGxhY2VtZW50XG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAzXSA9IE1hdGgucm91bmQob3kgKiA2NCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMVxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyA4XSAvKiB0ZXggKi8gPSBNYXRoLmZsb29yKHR4IC8gNCk7XG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDldIC8qIHRleCAqLyA9IE1hdGguZmxvb3IodHkgLyA0KTtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTBdIC8qIGxhYmVsbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKGxhYmVsbWluem9vbSkgKiAxMCk7XG5cbiAgICAgICAgLy8gYV9kYXRhMlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMl0gLyogbWluem9vbSAqLyA9IE1hdGguZmxvb3IoKG1pbnpvb20pICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcblxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGExLCA0LCBnbC5VTlNJR05FRF9CWVRFLCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA4KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMiwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgMTIpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2x5cGhWZXJ0ZXhCdWZmZXI7XG5cbmZ1bmN0aW9uIEdseXBoVmVydGV4QnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cbkdseXBoVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBkZWZhdWx0TGVuZ3RoOiAyMDQ4ICogMTYsXG4gICAgaXRlbVNpemU6IDE2LFxuXG4gICAgYWRkOiBmdW5jdGlvbih4LCB5LCBveCwgb3ksIHR4LCB0eSwgbWluem9vbSwgbWF4em9vbSwgbGFiZWxtaW56b29tKSB7XG4gICAgICAgIHZhciBwb3MgPSB0aGlzLnBvcyxcbiAgICAgICAgICAgIHBvczIgPSBwb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDBdID0geDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0geTtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDJdID0gTWF0aC5yb3VuZChveCAqIDY0KTsgLy8gdXNlIDEvNjQgcGl4ZWxzIGZvciBwbGFjZW1lbnRcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDNdID0gTWF0aC5yb3VuZChveSAqIDY0KTtcblxuICAgICAgICAvLyBhX2RhdGExXG4gICAgICAgIHRoaXMudWJ5dGVzW3BvcyArIDhdIC8qIHRleCAqLyA9IHR4IC8gNDtcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgOV0gLyogdGV4ICovID0gdHkgLyA0O1xuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxMF0gLyogbGFiZWxtaW56b29tICovID0gTWF0aC5mbG9vcigobGFiZWxtaW56b29tIHx8IDApICogMTApO1xuXG4gICAgICAgIC8vIGFfZGF0YTJcbiAgICAgICAgdGhpcy51Ynl0ZXNbcG9zICsgMTJdIC8qIG1pbnpvb20gKi8gPSBNYXRoLmZsb29yKChtaW56b29tIHx8IDApICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuICAgICAgICB0aGlzLnVieXRlc1twb3MgKyAxM10gLyogbWF4em9vbSAqLyA9IE1hdGguZmxvb3IoTWF0aC5taW4obWF4em9vbSB8fCAyNSwgMjUpICogMTApOyAvLyAxLzEwIHpvb20gbGV2ZWxzOiB6MTYgPT0gMTYwLlxuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfSxcblxuICAgIGJpbmQ6IGZ1bmN0aW9uKGdsLCBzaGFkZXIsIG9mZnNldCkge1xuICAgICAgICBCdWZmZXIucHJvdG90eXBlLmJpbmQuY2FsbCh0aGlzLCBnbCk7XG5cbiAgICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuaXRlbVNpemU7XG5cbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyAwKTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9vZmZzZXQsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCBvZmZzZXQgKyA0KTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9kYXRhMSwgNCwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgb2Zmc2V0ICsgOCk7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YTIsIDIsIGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlLCBzdHJpZGUsIG9mZnNldCArIDEyKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXIgPSByZXF1aXJlKCcuL2J1ZmZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVFbGVtZW50QnVmZmVyO1xuXG5mdW5jdGlvbiBMaW5lRWxlbWVudEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5MaW5lRWxlbWVudEJ1ZmZlci5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQnVmZmVyLCB7XG4gICAgaXRlbVNpemU6IDYsIC8vIGJ5dGVzIHBlciB0cmlhbmdsZSAoMyAqIHVuc2lnbmVkIHNob3J0ID09IDYgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDJdID0gYztcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwvdXRpbCcpO1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZVZlcnRleEJ1ZmZlcjtcblxuZnVuY3Rpb24gTGluZVZlcnRleEJ1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG4vLyBzY2FsZSB0aGUgZXh0cnVzaW9uIHZlY3RvciBzbyB0aGF0IHRoZSBub3JtYWwgbGVuZ3RoIGlzIHRoaXMgdmFsdWUuXG4vLyBjb250YWlucyB0aGUgXCJ0ZXh0dXJlXCIgbm9ybWFscyAoLTEuLjEpLiB0aGlzIGlzIGRpc3RpbmN0IGZyb20gdGhlIGV4dHJ1ZGVcbi8vIG5vcm1hbHMgZm9yIGxpbmUgam9pbnMsIGJlY2F1c2UgdGhlIHgtdmFsdWUgcmVtYWlucyAwIGZvciB0aGUgdGV4dHVyZVxuLy8gbm9ybWFsIGFycmF5LCB3aGlsZSB0aGUgZXh0cnVkZSBub3JtYWwgYWN0dWFsbHkgbW92ZXMgdGhlIHZlcnRleCB0byBjcmVhdGVcbi8vIHRoZSBhY3V0ZS9iZXZlbGxlZCBsaW5lIGpvaW4uXG5MaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZSA9IDYzO1xuXG5MaW5lVmVydGV4QnVmZmVyLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChCdWZmZXIsIHtcbiAgICBpdGVtU2l6ZTogOCwgLy8gYnl0ZXMgcGVyIHZlcnRleCAoMiAqIHNob3J0ICsgMSAqIHNob3J0ICsgMiAqIGJ5dGUgPSA4IGJ5dGVzKVxuICAgIGRlZmF1bHRMZW5ndGg6IDMyNzY4LFxuXG4gICAgLy8gYWRkIGEgdmVydGV4IHRvIHRoaXMgYnVmZmVyO1xuICAgIC8vIHgsIHkgLSB2ZXJ0ZXggcG9zaXRpb25cbiAgICAvLyBleCwgZXkgLSBleHRydWRlIG5vcm1hbFxuICAgIC8vIHR4LCB0eSAtIHRleHR1cmUgbm9ybWFsXG4gICAgYWRkOiBmdW5jdGlvbihwb2ludCwgZXh0cnVkZSwgdHgsIHR5LCBsaW5lc29mYXIpIHtcbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zLFxuICAgICAgICAgICAgcG9zMiA9IHBvcyAvIDIsXG4gICAgICAgICAgICBpbmRleCA9IHRoaXMuaW5kZXgsXG4gICAgICAgICAgICBleHRydWRlU2NhbGUgPSBMaW5lVmVydGV4QnVmZmVyLmV4dHJ1ZGVTY2FsZTtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2hvcnRzW3BvczIgKyAwXSA9IChNYXRoLmZsb29yKHBvaW50LngpICogMikgfCB0eDtcbiAgICAgICAgdGhpcy5zaG9ydHNbcG9zMiArIDFdID0gKE1hdGguZmxvb3IocG9pbnQueSkgKiAyKSB8IHR5O1xuXG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNF0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueCk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNV0gPSBNYXRoLnJvdW5kKGV4dHJ1ZGVTY2FsZSAqIGV4dHJ1ZGUueSk7XG4gICAgICAgIHRoaXMuYnl0ZXNbcG9zICsgNl0gPSAobGluZXNvZmFyIHx8IDApIC8gMTI4O1xuICAgICAgICB0aGlzLmJ5dGVzW3BvcyArIDddID0gKGxpbmVzb2ZhciB8fCAwKSAlIDEyODtcblxuICAgICAgICB0aGlzLnBvcyArPSB0aGlzLml0ZW1TaXplO1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBPdXRsaW5lRWxlbWVudHNCdWZmZXI7XG5cbmZ1bmN0aW9uIE91dGxpbmVFbGVtZW50c0J1ZmZlcihidWZmZXIpIHtcbiAgICBCdWZmZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xufVxuXG5PdXRsaW5lRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA0LCAvLyBieXRlcyBwZXIgbGluZSAoMiAqIHVuc2lnbmVkIHNob3J0ID09IDQgYnl0ZXMpXG4gICAgYXJyYXlUeXBlOiAnRUxFTUVOVF9BUlJBWV9CVUZGRVInLFxuXG4gICAgYWRkOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHZhciBwb3MyID0gdGhpcy5wb3MgLyAyO1xuXG4gICAgICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAwXSA9IGE7XG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMV0gPSBiO1xuXG4gICAgICAgIHRoaXMucG9zICs9IHRoaXMuaXRlbVNpemU7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsJyk7XG52YXIgQnVmZmVyID0gcmVxdWlyZSgnLi9idWZmZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyO1xuXG5mdW5jdGlvbiBUcmlhbmdsZUVsZW1lbnRzQnVmZmVyKGJ1ZmZlcikge1xuICAgIEJ1ZmZlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG59XG5cblRyaWFuZ2xlRWxlbWVudHNCdWZmZXIucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEJ1ZmZlciwge1xuICAgIGl0ZW1TaXplOiA2LCAvLyBieXRlcyBwZXIgdHJpYW5nbGUgKDMgKiB1bnNpZ25lZCBzaG9ydCA9PSA2IGJ5dGVzKVxuICAgIGFycmF5VHlwZTogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcblxuICAgIGFkZDogZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAgICB2YXIgcG9zMiA9IHRoaXMucG9zIC8gMjtcblxuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgICAgIHRoaXMudXNob3J0c1twb3MyICsgMF0gPSBhO1xuICAgICAgICB0aGlzLnVzaG9ydHNbcG9zMiArIDFdID0gYjtcbiAgICAgICAgdGhpcy51c2hvcnRzW3BvczIgKyAyXSA9IGM7XG5cbiAgICAgICAgdGhpcy5wb3MgKz0gdGhpcy5pdGVtU2l6ZTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCdWNrZXQ7XG5cbnZhciBMaW5lQnVja2V0ID0gcmVxdWlyZSgnLi9saW5lX2J1Y2tldCcpO1xudmFyIEZpbGxCdWNrZXQgPSByZXF1aXJlKCcuL2ZpbGxfYnVja2V0Jyk7XG52YXIgU3ltYm9sQnVja2V0ID0gcmVxdWlyZSgnLi9zeW1ib2xfYnVja2V0Jyk7XG52YXIgTGF5b3V0UHJvcGVydGllcyA9IHJlcXVpcmUoJy4uL3N0eWxlL2xheW91dF9wcm9wZXJ0aWVzJyk7XG52YXIgZmVhdHVyZUZpbHRlciA9IHJlcXVpcmUoJ2ZlYXR1cmUtZmlsdGVyJyk7XG52YXIgU3R5bGVEZWNsYXJhdGlvblNldCA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlX2RlY2xhcmF0aW9uX3NldCcpO1xuXG5mdW5jdGlvbiBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgeiwgb3ZlcnNjYWxpbmcsIGNvbGxpc2lvbkRlYnVnKSB7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBTdHlsZURlY2xhcmF0aW9uU2V0KCdsYXlvdXQnLCBsYXllci50eXBlLCBsYXllci5sYXlvdXQsIHt9KS52YWx1ZXMoKSxcbiAgICAgICAgZmFrZVpvb21IaXN0b3J5ID0geyBsYXN0SW50ZWdlclpvb206IEluZmluaXR5LCBsYXN0SW50ZWdlclpvb21UaW1lOiAwLCBsYXN0Wm9vbTogMCB9LFxuICAgICAgICBsYXlvdXQgPSB7fTtcblxuICAgIGZvciAodmFyIGsgaW4gdmFsdWVzKSB7XG4gICAgICAgIGxheW91dFtrXSA9IHZhbHVlc1trXS5jYWxjdWxhdGUoeiwgZmFrZVpvb21IaXN0b3J5KTtcbiAgICB9XG5cbiAgICB2YXIgQnVja2V0Q2xhc3MgPVxuICAgICAgICBsYXllci50eXBlID09PSAnbGluZScgPyBMaW5lQnVja2V0IDpcbiAgICAgICAgbGF5ZXIudHlwZSA9PT0gJ2ZpbGwnID8gRmlsbEJ1Y2tldCA6XG4gICAgICAgIGxheWVyLnR5cGUgPT09ICdzeW1ib2wnID8gU3ltYm9sQnVja2V0IDogbnVsbDtcblxuICAgIHZhciBidWNrZXQgPSBuZXcgQnVja2V0Q2xhc3MoYnVmZmVycywgbmV3IExheW91dFByb3BlcnRpZXNbbGF5ZXIudHlwZV0obGF5b3V0KSwgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpO1xuXG4gICAgYnVja2V0LmlkID0gbGF5ZXIuaWQ7XG4gICAgYnVja2V0LnR5cGUgPSBsYXllci50eXBlO1xuICAgIGJ1Y2tldFsnc291cmNlLWxheWVyJ10gPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgYnVja2V0LmludGVyYWN0aXZlID0gbGF5ZXIuaW50ZXJhY3RpdmU7XG4gICAgYnVja2V0Lm1pblpvb20gPSBsYXllci5taW56b29tO1xuICAgIGJ1Y2tldC5tYXhab29tID0gbGF5ZXIubWF4em9vbTtcbiAgICBidWNrZXQuZmlsdGVyID0gZmVhdHVyZUZpbHRlcihsYXllci5maWx0ZXIpO1xuICAgIGJ1Y2tldC5mZWF0dXJlcyA9IFtdO1xuXG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBFbGVtZW50R3JvdXBzO1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXBzKHZlcnRleEJ1ZmZlciwgZWxlbWVudEJ1ZmZlciwgc2Vjb25kRWxlbWVudEJ1ZmZlcikge1xuXG4gICAgdGhpcy52ZXJ0ZXhCdWZmZXIgPSB2ZXJ0ZXhCdWZmZXI7XG4gICAgdGhpcy5lbGVtZW50QnVmZmVyID0gZWxlbWVudEJ1ZmZlcjtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRCdWZmZXIgPSBzZWNvbmRFbGVtZW50QnVmZmVyO1xuICAgIHRoaXMuZ3JvdXBzID0gW107XG59XG5cbkVsZW1lbnRHcm91cHMucHJvdG90eXBlLm1ha2VSb29tRm9yID0gZnVuY3Rpb24obnVtVmVydGljZXMpIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudCB8fCB0aGlzLmN1cnJlbnQudmVydGV4TGVuZ3RoICsgbnVtVmVydGljZXMgPiA2NTUzNSkge1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSBuZXcgRWxlbWVudEdyb3VwKHRoaXMudmVydGV4QnVmZmVyLmluZGV4LFxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudEJ1ZmZlciAmJiB0aGlzLmVsZW1lbnRCdWZmZXIuaW5kZXgsXG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRFbGVtZW50QnVmZmVyICYmIHRoaXMuc2Vjb25kRWxlbWVudEJ1ZmZlci5pbmRleCk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBFbGVtZW50R3JvdXAodmVydGV4U3RhcnRJbmRleCwgZWxlbWVudFN0YXJ0SW5kZXgsIHNlY29uZEVsZW1lbnRTdGFydEluZGV4KSB7XG4gICAgLy8gdGhlIG9mZnNldCBpbnRvIHRoZSB2ZXJ0ZXggYnVmZmVyIG9mIHRoZSBmaXJzdCB2ZXJ0ZXggaW4gdGhpcyBncm91cFxuICAgIHRoaXMudmVydGV4U3RhcnRJbmRleCA9IHZlcnRleFN0YXJ0SW5kZXg7XG4gICAgdGhpcy5lbGVtZW50U3RhcnRJbmRleCA9IGVsZW1lbnRTdGFydEluZGV4O1xuICAgIHRoaXMuc2Vjb25kRWxlbWVudFN0YXJ0SW5kZXggPSBzZWNvbmRFbGVtZW50U3RhcnRJbmRleDtcbiAgICB0aGlzLmVsZW1lbnRMZW5ndGggPSAwO1xuICAgIHRoaXMudmVydGV4TGVuZ3RoID0gMDtcbiAgICB0aGlzLnNlY29uZEVsZW1lbnRMZW5ndGggPSAwO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmJ1c2ggPSByZXF1aXJlKCdyYnVzaCcpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciB2dCA9IHJlcXVpcmUoJ3ZlY3Rvci10aWxlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZlYXR1cmVUcmVlO1xuXG5mdW5jdGlvbiBGZWF0dXJlVHJlZShjb29yZCwgb3ZlcnNjYWxpbmcpIHtcbiAgICB0aGlzLnggPSBjb29yZC54O1xuICAgIHRoaXMueSA9IGNvb3JkLnk7XG4gICAgdGhpcy56ID0gY29vcmQueiAtIE1hdGgubG9nKG92ZXJzY2FsaW5nKSAvIE1hdGguTE4yO1xuICAgIHRoaXMucnRyZWUgPSByYnVzaCg5KTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZCA9IFtdO1xufVxuXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24oYmJveCwgbGF5ZXJzLCBmZWF0dXJlKSB7XG4gICAgYmJveC5sYXllcnMgPSBsYXllcnM7XG4gICAgYmJveC5mZWF0dXJlID0gZmVhdHVyZTtcbiAgICB0aGlzLnRvQmVJbnNlcnRlZC5wdXNoKGJib3gpO1xufTtcblxuLy8gYnVsayBpbnNlcnQgaW50byB0cmVlXG5GZWF0dXJlVHJlZS5wcm90b3R5cGUuX2xvYWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnJ0cmVlLmxvYWQodGhpcy50b0JlSW5zZXJ0ZWQpO1xuICAgIHRoaXMudG9CZUluc2VydGVkID0gW107XG59O1xuXG4vLyBGaW5kcyBmZWF0dXJlcyBpbiB0aGlzIHRpbGUgYXQgYSBwYXJ0aWN1bGFyIHBvc2l0aW9uLlxuRmVhdHVyZVRyZWUucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24oYXJncywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy50b0JlSW5zZXJ0ZWQubGVuZ3RoKSB0aGlzLl9sb2FkKCk7XG5cbiAgICB2YXIgcGFyYW1zID0gYXJncy5wYXJhbXMgfHwge30sXG4gICAgICAgIHJhZGl1cyA9IChwYXJhbXMucmFkaXVzIHx8IDApICogNDA5NiAvIGFyZ3Muc2NhbGUsXG4gICAgICAgIHggPSBhcmdzLngsXG4gICAgICAgIHkgPSBhcmdzLnksXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgdmFyIG1hdGNoaW5nID0gdGhpcy5ydHJlZS5zZWFyY2goWyB4IC0gcmFkaXVzLCB5IC0gcmFkaXVzLCB4ICsgcmFkaXVzLCB5ICsgcmFkaXVzIF0pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZlYXR1cmUgPSBtYXRjaGluZ1tpXS5mZWF0dXJlLFxuICAgICAgICAgICAgbGF5ZXJzID0gbWF0Y2hpbmdbaV0ubGF5ZXJzLFxuICAgICAgICAgICAgdHlwZSA9IHZ0LlZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW2ZlYXR1cmUudHlwZV07XG5cbiAgICAgICAgaWYgKHBhcmFtcy4kdHlwZSAmJiB0eXBlICE9PSBwYXJhbXMuJHR5cGUpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgaWYgKCFnZW9tZXRyeUNvbnRhaW5zUG9pbnQoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSwgdHlwZSwgbmV3IFBvaW50KHgsIHkpLCByYWRpdXMpKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIGdlb0pTT04gPSBmZWF0dXJlLnRvR2VvSlNPTih0aGlzLngsIHRoaXMueSwgdGhpcy56KTtcbiAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCBsYXllcnMubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IGxheWVyc1tsXTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5sYXllciAmJiBsYXllciAhPT0gcGFyYW1zLmxheWVyLmlkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICByZXN1bHQucHVzaCh1dGlsLmV4dGVuZCh7bGF5ZXI6IGxheWVyfSwgZ2VvSlNPTikpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0KTtcbn07XG5cbmZ1bmN0aW9uIGdlb21ldHJ5Q29udGFpbnNQb2ludChyaW5ncywgdHlwZSwgcCwgcmFkaXVzKSB7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdQb2ludCcgPyBwb2ludENvbnRhaW5zUG9pbnQocmluZ3MsIHAsIHJhZGl1cykgOlxuICAgICAgICAgICB0eXBlID09PSAnTGluZVN0cmluZycgPyBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6XG4gICAgICAgICAgIHR5cGUgPT09ICdQb2x5Z29uJyA/IHBvbHlDb250YWluc1BvaW50KHJpbmdzLCBwKSB8fCBsaW5lQ29udGFpbnNQb2ludChyaW5ncywgcCwgcmFkaXVzKSA6IGZhbHNlO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTUwMTcyNS8zMzEzNzkuXG5mdW5jdGlvbiBkaXN0VG9TZWdtZW50U3F1YXJlZChwLCB2LCB3KSB7XG4gICAgdmFyIGwyID0gdi5kaXN0U3FyKHcpO1xuICAgIGlmIChsMiA9PT0gMCkgcmV0dXJuIHAuZGlzdFNxcih2KTtcbiAgICB2YXIgdCA9ICgocC54IC0gdi54KSAqICh3LnggLSB2LngpICsgKHAueSAtIHYueSkgKiAody55IC0gdi55KSkgLyBsMjtcbiAgICBpZiAodCA8IDApIHJldHVybiBwLmRpc3RTcXIodik7XG4gICAgaWYgKHQgPiAxKSByZXR1cm4gcC5kaXN0U3FyKHcpO1xuICAgIHJldHVybiBwLmRpc3RTcXIody5zdWIodikuX211bHQodCkuX2FkZCh2KSk7XG59XG5cbmZ1bmN0aW9uIGxpbmVDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAvLyBGaW5kIGxpbmUgc2VnbWVudHMgdGhhdCBoYXZlIGEgZGlzdGFuY2UgPD0gcmFkaXVzXjIgdG8gcFxuICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlLCB3ZSB0cmVhdCB0aGUgbGluZSBhcyBcImNvbnRhaW5pbmcgcG9pbnQgcFwiLlxuICAgICAgICAgICAgdmFyIHYgPSByaW5nW2ogLSAxXSwgdyA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoZGlzdFRvU2VnbWVudFNxdWFyZWQocCwgdiwgdykgPCByKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIHBvaW50IGluIHBvbHlnb24gcmF5IGNhc3RpbmcgYWxnb3JpdGhtXG5mdW5jdGlvbiBwb2x5Q29udGFpbnNQb2ludChyaW5ncywgcCkge1xuICAgIHZhciBjID0gZmFsc2UsXG4gICAgICAgIHJpbmcsIHAxLCBwMjtcblxuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgcmluZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgcmluZyA9IHJpbmdzW2tdO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHJpbmcubGVuZ3RoIC0gMTsgaSA8IHJpbmcubGVuZ3RoOyBqID0gaSsrKSB7XG4gICAgICAgICAgICBwMSA9IHJpbmdbaV07XG4gICAgICAgICAgICBwMiA9IHJpbmdbal07XG4gICAgICAgICAgICBpZiAoKChwMS55ID4gcC55KSAhPT0gKHAyLnkgPiBwLnkpKSAmJiAocC54IDwgKHAyLnggLSBwMS54KSAqIChwLnkgLSBwMS55KSAvIChwMi55IC0gcDEueSkgKyBwMS54KSkge1xuICAgICAgICAgICAgICAgIGMgPSAhYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gcG9pbnRDb250YWluc1BvaW50KHJpbmdzLCBwLCByYWRpdXMpIHtcbiAgICB2YXIgciA9IHJhZGl1cyAqIHJhZGl1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByaW5nLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAocmluZ1tqXS5kaXN0U3FyKHApIDw9IHIpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmlsbEJ1Y2tldDtcblxuZnVuY3Rpb24gRmlsbEJ1Y2tldChidWZmZXJzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmZpbGxWZXJ0ZXgsIGJ1ZmZlcnMuZmlsbEVsZW1lbnQsIGJ1ZmZlcnMub3V0bGluZUVsZW1lbnQpO1xufVxuXG5GaWxsQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmZWF0dXJlcyA9IHRoaXMuZmVhdHVyZXM7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xuICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZmVhdHVyZS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxufTtcblxuRmlsbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmFkZEZpbGwobGluZXNbaV0pO1xuICAgIH1cbn07XG5cbkZpbGxCdWNrZXQucHJvdG90eXBlLmFkZEZpbGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIGlmICh2ZXJ0aWNlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgIC8vY29uc29sZS53YXJuKCdhIGZpbGwgbXVzdCBoYXZlIGF0IGxlYXN0IHRocmVlIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiB2ZXJ0aWNlcyB3ZSdyZSBnb2luZyB0byBwcm9kdWNlIHNvIHRoYXQgd2VcbiAgICAvLyBjYW4gcmVzaXplIHRoZSBidWZmZXIgYmVmb3JlaGFuZCwgb3IgZGV0ZWN0IHdoZXRoZXIgdGhlIGN1cnJlbnQgbGluZVxuICAgIC8vIHdvbid0IGZpdCBpbnRvIHRoZSBidWZmZXIgYW55bW9yZS5cbiAgICAvLyBJbiBvcmRlciB0byBiZSBhYmxlIHRvIHVzZSB0aGUgdmVydGV4IGJ1ZmZlciBmb3IgZHJhd2luZyB0aGUgYW50aWFsaWFzZWRcbiAgICAvLyBvdXRsaW5lcywgd2Ugc2VwYXJhdGUgYWxsIHBvbHlnb24gdmVydGljZXMgd2l0aCBhIGRlZ2VuZXJhdGUgKG91dC1vZi1cbiAgICAvLyB2aWV3cGxhbmUpIHZlcnRleC5cblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG5cbiAgICAvLyBDaGVjayB3aGV0aGVyIHRoaXMgZ2VvbWV0cnkgYnVmZmVyIGNhbiBob2xkIGFsbCB0aGUgcmVxdWlyZWQgdmVydGljZXMuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLm1ha2VSb29tRm9yKGxlbiArIDEpO1xuICAgIHZhciBlbGVtZW50R3JvdXAgPSB0aGlzLmVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciBmaWxsVmVydGV4ID0gdGhpcy5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmFyIGZpbGxFbGVtZW50ID0gdGhpcy5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIHZhciBvdXRsaW5lRWxlbWVudCA9IHRoaXMuYnVmZmVycy5vdXRsaW5lRWxlbWVudDtcblxuICAgIC8vIFdlJ3JlIGdlbmVyYXRpbmcgdHJpYW5nbGUgZmFucywgc28gd2UgYWx3YXlzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IGNvb3JkaW5hdGUgaW4gdGhpcyBwb2x5Z29uLlxuICAgIHZhciBmaXJzdEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4LFxuICAgICAgICBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCwgY3VycmVudFZlcnRleDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudEluZGV4ID0gZmlsbFZlcnRleC5pbmRleCAtIGVsZW1lbnRHcm91cC52ZXJ0ZXhTdGFydEluZGV4O1xuICAgICAgICBjdXJyZW50VmVydGV4ID0gdmVydGljZXNbaV07XG5cbiAgICAgICAgZmlsbFZlcnRleC5hZGQoY3VycmVudFZlcnRleC54LCBjdXJyZW50VmVydGV4LnkpO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoKys7XG5cbiAgICAgICAgLy8gT25seSBhZGQgdHJpYW5nbGVzIHRoYXQgaGF2ZSBkaXN0aW5jdCB2ZXJ0aWNlcy5cbiAgICAgICAgaWYgKGkgPj0gMiAmJiAoY3VycmVudFZlcnRleC54ICE9PSB2ZXJ0aWNlc1swXS54IHx8IGN1cnJlbnRWZXJ0ZXgueSAhPT0gdmVydGljZXNbMF0ueSkpIHtcbiAgICAgICAgICAgIGZpbGxFbGVtZW50LmFkZChmaXJzdEluZGV4LCBwcmV2SW5kZXgsIGN1cnJlbnRJbmRleCk7XG4gICAgICAgICAgICBlbGVtZW50R3JvdXAuZWxlbWVudExlbmd0aCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGkgPj0gMSkge1xuICAgICAgICAgICAgb3V0bGluZUVsZW1lbnQuYWRkKHByZXZJbmRleCwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cC5zZWNvbmRFbGVtZW50TGVuZ3RoKys7XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2SW5kZXggPSBjdXJyZW50SW5kZXg7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEVsZW1lbnRHcm91cHMgPSByZXF1aXJlKCcuL2VsZW1lbnRfZ3JvdXBzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTGluZUJ1Y2tldDtcblxuZnVuY3Rpb24gTGluZUJ1Y2tldChidWZmZXJzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcbiAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmxpbmVWZXJ0ZXgsIGJ1ZmZlcnMubGluZUVsZW1lbnQpO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG59XG5cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaV07XG4gICAgICAgIHRoaXMuYWRkRmVhdHVyZShmZWF0dXJlLmxvYWRHZW9tZXRyeSgpKTtcbiAgICB9XG59O1xuXG5MaW5lQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlID0gZnVuY3Rpb24obGluZXMpIHtcbiAgICB2YXIgbGF5b3V0UHJvcGVydGllcyA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuYWRkTGluZShsaW5lc1tpXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtam9pbiddLFxuICAgICAgICAgICAgbGF5b3V0UHJvcGVydGllc1snbGluZS1jYXAnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtbWl0ZXItbGltaXQnXSxcbiAgICAgICAgICAgIGxheW91dFByb3BlcnRpZXNbJ2xpbmUtcm91bmQtbGltaXQnXSk7XG4gICAgfVxufTtcblxuTGluZUJ1Y2tldC5wcm90b3R5cGUuYWRkTGluZSA9IGZ1bmN0aW9uKHZlcnRpY2VzLCBqb2luLCBjYXAsIG1pdGVyTGltaXQsIHJvdW5kTGltaXQpIHtcblxuICAgIHZhciBsZW4gPSB2ZXJ0aWNlcy5sZW5ndGg7XG4gICAgLy8gSWYgdGhlIGxpbmUgaGFzIGR1cGxpY2F0ZSB2ZXJ0aWNlcyBhdCB0aGUgZW5kLCBhZGp1c3QgbGVuZ3RoIHRvIHJlbW92ZSB0aGVtLlxuICAgIHdoaWxlIChsZW4gPiAyICYmIHZlcnRpY2VzW2xlbiAtIDFdLmVxdWFscyh2ZXJ0aWNlc1tsZW4gLSAyXSkpIHtcbiAgICAgICAgbGVuLS07XG4gICAgfVxuXG4gICAgaWYgKHZlcnRpY2VzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgLy9jb25zb2xlLndhcm4oJ2EgbGluZSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHZlcnRpY2VzJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoam9pbiA9PT0gJ2JldmVsJykgbWl0ZXJMaW1pdCA9IDEuMDU7XG5cbiAgICB2YXIgZmlyc3RWZXJ0ZXggPSB2ZXJ0aWNlc1swXSxcbiAgICAgICAgbGFzdFZlcnRleCA9IHZlcnRpY2VzW2xlbiAtIDFdLFxuICAgICAgICBjbG9zZWQgPSBmaXJzdFZlcnRleC5lcXVhbHMobGFzdFZlcnRleCk7XG5cbiAgICAvLyB3ZSBjb3VsZCBiZSBtb3JlIHByZWNpc2UsIGJ1dCBpdCB3b3VsZCBvbmx5IHNhdmUgYSBuZWdsaWdpYmxlIGFtb3VudCBvZiBzcGFjZVxuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5tYWtlUm9vbUZvcihsZW4gKiA0KTtcblxuICAgIGlmIChsZW4gPT09IDIgJiYgY2xvc2VkKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignYSBsaW5lIG1heSBub3QgaGF2ZSBjb2luY2lkZW50IHBvaW50cycpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGJlZ2luQ2FwID0gY2FwLFxuICAgICAgICBlbmRDYXAgPSBjbG9zZWQgPyAnYnV0dCcgOiBjYXAsXG4gICAgICAgIGZsaXAgPSAxLFxuICAgICAgICBkaXN0YW5jZSA9IDAsXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gdHJ1ZSxcbiAgICAgICAgY3VycmVudFZlcnRleCwgcHJldlZlcnRleCwgbmV4dFZlcnRleCwgcHJldk5vcm1hbCwgbmV4dE5vcm1hbCwgb2Zmc2V0QSwgb2Zmc2V0QjtcblxuICAgIC8vIHRoZSBsYXN0IHRocmVlIHZlcnRpY2VzIGFkZGVkXG4gICAgdGhpcy5lMSA9IHRoaXMuZTIgPSB0aGlzLmUzID0gLTE7XG5cbiAgICBpZiAoY2xvc2VkKSB7XG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tsZW4gLSAyXTtcbiAgICAgICAgbmV4dE5vcm1hbCA9IGZpcnN0VmVydGV4LnN1YihjdXJyZW50VmVydGV4KS5fdW5pdCgpLl9wZXJwKCk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgIG5leHRWZXJ0ZXggPSBjbG9zZWQgJiYgaSA9PT0gbGVuIC0gMSA/XG4gICAgICAgICAgICB2ZXJ0aWNlc1sxXSA6IC8vIGlmIHRoZSBsaW5lIGlzIGNsb3NlZCwgd2UgdHJlYXQgdGhlIGxhc3QgdmVydGV4IGxpa2UgdGhlIGZpcnN0XG4gICAgICAgICAgICB2ZXJ0aWNlc1tpICsgMV07IC8vIGp1c3QgdGhlIG5leHQgdmVydGV4XG5cbiAgICAgICAgLy8gaWYgdHdvIGNvbnNlY3V0aXZlIHZlcnRpY2VzIGV4aXN0LCBza2lwIHRoZSBjdXJyZW50IG9uZVxuICAgICAgICBpZiAobmV4dFZlcnRleCAmJiB2ZXJ0aWNlc1tpXS5lcXVhbHMobmV4dFZlcnRleCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChuZXh0Tm9ybWFsKSBwcmV2Tm9ybWFsID0gbmV4dE5vcm1hbDtcbiAgICAgICAgaWYgKGN1cnJlbnRWZXJ0ZXgpIHByZXZWZXJ0ZXggPSBjdXJyZW50VmVydGV4O1xuXG4gICAgICAgIGN1cnJlbnRWZXJ0ZXggPSB2ZXJ0aWNlc1tpXTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgaG93IGZhciBhbG9uZyB0aGUgbGluZSB0aGUgY3VycmVudFZlcnRleCBpc1xuICAgICAgICBpZiAocHJldlZlcnRleCkgZGlzdGFuY2UgKz0gY3VycmVudFZlcnRleC5kaXN0KHByZXZWZXJ0ZXgpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbm9ybWFsIHRvd2FyZHMgdGhlIG5leHQgdmVydGV4IGluIHRoaXMgbGluZS4gSW4gY2FzZVxuICAgICAgICAvLyB0aGVyZSBpcyBubyBuZXh0IHZlcnRleCwgcHJldGVuZCB0aGF0IHRoZSBsaW5lIGlzIGNvbnRpbnVpbmcgc3RyYWlnaHQsXG4gICAgICAgIC8vIG1lYW5pbmcgdGhhdCB3ZSBhcmUganVzdCB1c2luZyB0aGUgcHJldmlvdXMgbm9ybWFsLlxuICAgICAgICBuZXh0Tm9ybWFsID0gbmV4dFZlcnRleCA/IG5leHRWZXJ0ZXguc3ViKGN1cnJlbnRWZXJ0ZXgpLl91bml0KCkuX3BlcnAoKSA6IHByZXZOb3JtYWw7XG5cbiAgICAgICAgLy8gSWYgd2Ugc3RpbGwgZG9uJ3QgaGF2ZSBhIHByZXZpb3VzIG5vcm1hbCwgdGhpcyBpcyB0aGUgYmVnaW5uaW5nIG9mIGFcbiAgICAgICAgLy8gbm9uLWNsb3NlZCBsaW5lLCBzbyB3ZSdyZSBkb2luZyBhIHN0cmFpZ2h0IFwiam9pblwiLlxuICAgICAgICBwcmV2Tm9ybWFsID0gcHJldk5vcm1hbCB8fCBuZXh0Tm9ybWFsO1xuXG4gICAgICAgIC8vIERldGVybWluZSB0aGUgbm9ybWFsIG9mIHRoZSBqb2luIGV4dHJ1c2lvbi4gSXQgaXMgdGhlIGFuZ2xlIGJpc2VjdG9yXG4gICAgICAgIC8vIG9mIHRoZSBzZWdtZW50cyBiZXR3ZWVuIHRoZSBwcmV2aW91cyBsaW5lIGFuZCB0aGUgbmV4dCBsaW5lLlxuICAgICAgICB2YXIgam9pbk5vcm1hbCA9IHByZXZOb3JtYWwuYWRkKG5leHROb3JtYWwpLl91bml0KCk7XG5cbiAgICAgICAgLyogIGpvaW5Ob3JtYWwgICAgIHByZXZOb3JtYWxcbiAgICAgICAgICogICAgICAgICAgICAg4oaWICAgICAg4oaRXG4gICAgICAgICAqICAgICAgICAgICAgICAgIC5fX19fX19fXy4gcHJldlZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqIG5leHROb3JtYWwgIOKGkCAgfCAgY3VycmVudFZlcnRleFxuICAgICAgICAgKiAgICAgICAgICAgICAgICB8XG4gICAgICAgICAqICAgICBuZXh0VmVydGV4ICFcbiAgICAgICAgICpcbiAgICAgICAgICovXG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBsZW5ndGggb2YgdGhlIG1pdGVyICh0aGUgcmF0aW8gb2YgdGhlIG1pdGVyIHRvIHRoZSB3aWR0aCkuXG4gICAgICAgIC8vIEZpbmQgdGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgbmV4dCBhbmQgam9pbiBub3JtYWxzXG4gICAgICAgIC8vIHVzaW5nIGRvdCBwcm9kdWN0LiBUaGUgaW52ZXJzZSBvZiB0aGF0IGlzIHRoZSBtaXRlciBsZW5ndGguXG4gICAgICAgIHZhciBjb3NIYWxmQW5nbGUgPSBqb2luTm9ybWFsLnggKiBuZXh0Tm9ybWFsLnggKyBqb2luTm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnk7XG4gICAgICAgIHZhciBtaXRlckxlbmd0aCA9IDEgLyBjb3NIYWxmQW5nbGU7XG5cbiAgICAgICAgLy8gVGhlIGpvaW4gaWYgYSBtaWRkbGUgdmVydGV4LCBvdGhlcndpc2UgdGhlIGNhcC5cbiAgICAgICAgdmFyIG1pZGRsZVZlcnRleCA9IHByZXZWZXJ0ZXggJiYgbmV4dFZlcnRleDtcbiAgICAgICAgdmFyIGN1cnJlbnRKb2luID0gbWlkZGxlVmVydGV4ID8gam9pbiA6IG5leHRWZXJ0ZXggPyBiZWdpbkNhcCA6IGVuZENhcDtcblxuICAgICAgICBpZiAobWlkZGxlVmVydGV4ICYmIGN1cnJlbnRKb2luID09PSAncm91bmQnICYmIG1pdGVyTGVuZ3RoIDwgcm91bmRMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInICYmIG1pdGVyTGVuZ3RoID4gbWl0ZXJMaW1pdCkge1xuICAgICAgICAgICAgY3VycmVudEpvaW4gPSAnYmV2ZWwnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBUaGUgbWF4aW11bSBleHRydWRlIGxlbmd0aCBpcyAxMjggLyA2MyA9IDIgdGltZXMgdGhlIHdpZHRoIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICAvLyBzbyBpZiBtaXRlckxlbmd0aCA+PSAyIHdlIG5lZWQgdG8gZHJhdyBhIGRpZmZlcmVudCB0eXBlIG9mIGJldmVsIHdoZXJlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoID4gMikgY3VycmVudEpvaW4gPSAnZmxpcGJldmVsJztcblxuICAgICAgICAgICAgLy8gSWYgdGhlIG1pdGVyTGVuZ3RoIGlzIHJlYWxseSBzbWFsbCBhbmQgdGhlIGxpbmUgYmV2ZWwgd291bGRuJ3QgYmUgdmlzaWJsZSxcbiAgICAgICAgICAgIC8vIGp1c3QgZHJhdyBhIG1pdGVyIGpvaW4gdG8gc2F2ZSBhIHRyaWFuZ2xlLlxuICAgICAgICAgICAgaWYgKG1pdGVyTGVuZ3RoIDwgbWl0ZXJMaW1pdCkgY3VycmVudEpvaW4gPSAnbWl0ZXInO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRKb2luID09PSAnbWl0ZXInKSB7XG4gICAgICAgICAgICBqb2luTm9ybWFsLl9tdWx0KG1pdGVyTGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgam9pbk5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdmbGlwYmV2ZWwnKSB7XG4gICAgICAgICAgICAvLyBtaXRlciBpcyB0b28gYmlnLCBmbGlwIHRoZSBkaXJlY3Rpb24gdG8gbWFrZSBhIGJldmVsZWQgam9pblxuXG4gICAgICAgICAgICBpZiAobWl0ZXJMZW5ndGggPiAxMDApIHtcbiAgICAgICAgICAgICAgICAvLyBBbG1vc3QgcGFyYWxsZWwgbGluZXNcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsID0gbmV4dE5vcm1hbC5jbG9uZSgpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBwcmV2Tm9ybWFsLnggKiBuZXh0Tm9ybWFsLnkgLSBwcmV2Tm9ybWFsLnkgKiBuZXh0Tm9ybWFsLnggPiAwID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgIHZhciBiZXZlbExlbmd0aCA9IG1pdGVyTGVuZ3RoICogcHJldk5vcm1hbC5hZGQobmV4dE5vcm1hbCkubWFnKCkgLyBwcmV2Tm9ybWFsLnN1YihuZXh0Tm9ybWFsKS5tYWcoKTtcbiAgICAgICAgICAgICAgICBqb2luTm9ybWFsLl9wZXJwKCkuX211bHQoYmV2ZWxMZW5ndGggKiBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBqb2luTm9ybWFsLCAwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICBmbGlwID0gLWZsaXA7XG5cbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Sm9pbiA9PT0gJ2JldmVsJykge1xuICAgICAgICAgICAgdmFyIGRpciA9IHByZXZOb3JtYWwueCAqIG5leHROb3JtYWwueSAtIHByZXZOb3JtYWwueSAqIG5leHROb3JtYWwueDtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAtTWF0aC5zcXJ0KG1pdGVyTGVuZ3RoICogbWl0ZXJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGlmIChmbGlwICogZGlyID4gMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldEEgPSAwO1xuICAgICAgICAgICAgICAgIG9mZnNldEIgPSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJldmVsXG4gICAgICAgICAgICBpZiAoIXN0YXJ0T2ZMaW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCBvZmZzZXRBLCBvZmZzZXRCLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC1vZmZzZXRBLCAtb2Zmc2V0QiwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdidXR0Jykge1xuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBhIGJ1dHRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIHByZXZOb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RhcnQgbmV4dCBzZWdtZW50IHdpdGggYSBidXR0XG4gICAgICAgICAgICBpZiAobmV4dFZlcnRleCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQ3VycmVudFZlcnRleChjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbmV4dE5vcm1hbCwgMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdzcXVhcmUnKSB7XG5cbiAgICAgICAgICAgIGlmICghc3RhcnRPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAvLyBDbG9zZSBwcmV2aW91cyBzZWdtZW50IHdpdGggYSBzcXVhcmUgY2FwXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgc2VnbWVudCBpcyBkb25lLiBVbnNldCB2ZXJ0aWNlcyB0byBkaXNjb25uZWN0IHNlZ21lbnRzLlxuICAgICAgICAgICAgICAgIHRoaXMuZTEgPSB0aGlzLmUyID0gLTE7XG4gICAgICAgICAgICAgICAgZmxpcCA9IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEpvaW4gPT09ICdyb3VuZCcpIHtcblxuICAgICAgICAgICAgaWYgKCFzdGFydE9mTGluZSkge1xuICAgICAgICAgICAgICAgIC8vIENsb3NlIHByZXZpb3VzIHNlZ21lbnQgd2l0aCBidXR0XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAwLCAwLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgcm91bmQgY2FwIG9yIGxpbmVqb2luIGF0IGVuZCBvZiBzZWdtZW50XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDdXJyZW50VmVydGV4KGN1cnJlbnRWZXJ0ZXgsIGZsaXAsIGRpc3RhbmNlLCBwcmV2Tm9ybWFsLCAxLCAxLCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSBzZWdtZW50IGlzIGRvbmUuIFVuc2V0IHZlcnRpY2VzIHRvIGRpc2Nvbm5lY3Qgc2VnbWVudHMuXG4gICAgICAgICAgICAgICAgdGhpcy5lMSA9IHRoaXMuZTIgPSAtMTtcbiAgICAgICAgICAgICAgICBmbGlwID0gMTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChiZWdpbkNhcCA9PT0gJ3JvdW5kJykge1xuICAgICAgICAgICAgICAgIC8vIEFkZCByb3VuZCBjYXAgYmVmb3JlIGZpcnN0IHNlZ21lbnRcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIC0xLCAtMSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IG5leHQgc2VnbWVudCB3aXRoIGEgYnV0dFxuICAgICAgICAgICAgaWYgKG5leHRWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoY3VycmVudFZlcnRleCwgZmxpcCwgZGlzdGFuY2UsIG5leHROb3JtYWwsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZMaW5lID0gZmFsc2U7XG4gICAgfVxuXG5cbn07XG5cbi8qKlxuICogQWRkIHR3byB2ZXJ0aWNlcyB0byB0aGUgYnVmZmVycy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3VycmVudFZlcnRleCB0aGUgbGluZSB2ZXJ0ZXggdG8gYWRkIGJ1ZmZlciB2ZXJ0aWNlcyBmb3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBmbGlwIC0xIGlmIHRoZSB2ZXJ0aWNlcyBzaG91bGQgYmUgZmxpcHBlZCwgMSBvdGhlcndpc2VcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZSB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgYmVnZ2luaW5nIG9mIHRoZSBsaW5lIHRvIHRoZSB2ZXJ0ZXhcbiAqIEBwYXJhbSB7TnVtYmVyfSBlbmRMZWZ0IGV4dHJ1ZGUgdG8gc2hpZnQgdGhlIGxlZnQgdmVydGV4IGFsb25nIHRoZSBsaW5lXG4gKiBAcGFyYW0ge051bWJlcn0gZW5kUmlnaHQgZXh0cnVkZSB0byBzaGlmdCB0aGUgbGVmdCB2ZXJ0ZXggYWxvbmcgdGhlIGxpbmVcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gcm91bmQgd2hldGhlciB0aGlzIGlzIGEgcm91bmQgY2FwXG4gKi9cbkxpbmVCdWNrZXQucHJvdG90eXBlLmFkZEN1cnJlbnRWZXJ0ZXggPSBmdW5jdGlvbihjdXJyZW50VmVydGV4LCBmbGlwLCBkaXN0YW5jZSwgbm9ybWFsLCBlbmRMZWZ0LCBlbmRSaWdodCwgcm91bmQpIHtcbiAgICB2YXIgdHggPSByb3VuZCA/IDEgOiAwO1xuICAgIHZhciBleHRydWRlO1xuXG4gICAgdmFyIGxpbmVWZXJ0ZXggPSB0aGlzLmJ1ZmZlcnMubGluZVZlcnRleDtcbiAgICB2YXIgbGluZUVsZW1lbnQgPSB0aGlzLmJ1ZmZlcnMubGluZUVsZW1lbnQ7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IHRoaXMuZWxlbWVudEdyb3Vwcy5jdXJyZW50O1xuICAgIHZhciB2ZXJ0ZXhTdGFydEluZGV4ID0gdGhpcy5lbGVtZW50R3JvdXBzLmN1cnJlbnQudmVydGV4U3RhcnRJbmRleDtcblxuICAgIGV4dHJ1ZGUgPSBub3JtYWwubXVsdChmbGlwKTtcbiAgICBpZiAoZW5kTGVmdCkgZXh0cnVkZS5fc3ViKG5vcm1hbC5wZXJwKCkuX211bHQoZW5kTGVmdCkpO1xuICAgIHRoaXMuZTMgPSBsaW5lVmVydGV4LmFkZChjdXJyZW50VmVydGV4LCBleHRydWRlLCB0eCwgMCwgZGlzdGFuY2UpIC0gdmVydGV4U3RhcnRJbmRleDtcbiAgICBpZiAodGhpcy5lMSA+PSAwICYmIHRoaXMuZTIgPj0gMCkge1xuICAgICAgICBsaW5lRWxlbWVudC5hZGQodGhpcy5lMSwgdGhpcy5lMiwgdGhpcy5lMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoKys7XG4gICAgfVxuICAgIHRoaXMuZTEgPSB0aGlzLmUyO1xuICAgIHRoaXMuZTIgPSB0aGlzLmUzO1xuXG4gICAgZXh0cnVkZSA9IG5vcm1hbC5tdWx0KC1mbGlwKTtcbiAgICBpZiAoZW5kUmlnaHQpIGV4dHJ1ZGUuX3N1Yihub3JtYWwucGVycCgpLl9tdWx0KGVuZFJpZ2h0KSk7XG4gICAgdGhpcy5lMyA9IGxpbmVWZXJ0ZXguYWRkKGN1cnJlbnRWZXJ0ZXgsIGV4dHJ1ZGUsIHR4LCAxLCBkaXN0YW5jZSkgLSB2ZXJ0ZXhTdGFydEluZGV4O1xuICAgIGlmICh0aGlzLmUxID49IDAgJiYgdGhpcy5lMiA+PSAwKSB7XG4gICAgICAgIGxpbmVFbGVtZW50LmFkZCh0aGlzLmUxLCB0aGlzLmUyLCB0aGlzLmUzKTtcbiAgICAgICAgZWxlbWVudEdyb3VwLmVsZW1lbnRMZW5ndGgrKztcbiAgICB9XG4gICAgdGhpcy5lMSA9IHRoaXMuZTI7XG4gICAgdGhpcy5lMiA9IHRoaXMuZTM7XG5cbiAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRWxlbWVudEdyb3VwcyA9IHJlcXVpcmUoJy4vZWxlbWVudF9ncm91cHMnKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG52YXIgZ2V0QW5jaG9ycyA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nZXRfYW5jaG9ycycpO1xudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG52YXIgUXVhZHMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcXVhZHMnKTtcbnZhciBTaGFwaW5nID0gcmVxdWlyZSgnLi4vc3ltYm9sL3NoYXBpbmcnKTtcbnZhciByZXNvbHZlVGV4dCA9IHJlcXVpcmUoJy4uL3N5bWJvbC9yZXNvbHZlX3RleHQnKTtcbnZhciByZXNvbHZlSWNvbnMgPSByZXF1aXJlKCcuLi9zeW1ib2wvcmVzb2x2ZV9pY29ucycpO1xudmFyIG1lcmdlTGluZXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvbWVyZ2VsaW5lcycpO1xudmFyIHNoYXBlVGV4dCA9IFNoYXBpbmcuc2hhcGVUZXh0O1xudmFyIHNoYXBlSWNvbiA9IFNoYXBpbmcuc2hhcGVJY29uO1xudmFyIGdldEdseXBoUXVhZHMgPSBRdWFkcy5nZXRHbHlwaFF1YWRzO1xudmFyIGdldEljb25RdWFkcyA9IFF1YWRzLmdldEljb25RdWFkcztcbnZhciBjbGlwTGluZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9jbGlwX2xpbmUnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbnZhciBDb2xsaXNpb25GZWF0dXJlID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl9mZWF0dXJlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU3ltYm9sQnVja2V0O1xuXG5mdW5jdGlvbiBTeW1ib2xCdWNrZXQoYnVmZmVycywgbGF5b3V0UHJvcGVydGllcywgY29sbGlzaW9uLCBvdmVyc2NhbGluZywgY29sbGlzaW9uRGVidWcpIHtcbiAgICB0aGlzLmJ1ZmZlcnMgPSBidWZmZXJzO1xuICAgIHRoaXMubGF5b3V0UHJvcGVydGllcyA9IGxheW91dFByb3BlcnRpZXM7XG4gICAgdGhpcy5jb2xsaXNpb24gPSBjb2xsaXNpb247XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IG92ZXJzY2FsaW5nO1xuICAgIHRoaXMuY29sbGlzaW9uRGVidWcgPSBjb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3ltYm9sSW5zdGFuY2VzID0gW107XG5cbn1cblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRGZWF0dXJlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgdGV4dEZlYXR1cmVzID0gdGhpcy50ZXh0RmVhdHVyZXM7XG5cbiAgICB2YXIgaG9yaXpvbnRhbEFsaWduID0gMC41LFxuICAgICAgICB2ZXJ0aWNhbEFsaWduID0gMC41O1xuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBjYXNlICd0b3AtcmlnaHQnOlxuICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgICAgaG9yaXpvbnRhbEFsaWduID0gMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICBjYXNlICdib3R0b20tbGVmdCc6XG4gICAgICAgICAgICBob3Jpem9udGFsQWxpZ24gPSAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChsYXlvdXRbJ3RleHQtYW5jaG9yJ10pIHtcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgY2FzZSAnYm90dG9tLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgY2FzZSAndG9wLXJpZ2h0JzpcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICAgICAgdmVydGljYWxBbGlnbiA9IDA7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2YXIganVzdGlmeSA9IGxheW91dFsndGV4dC1qdXN0aWZ5J10gPT09ICdyaWdodCcgPyAxIDpcbiAgICAgICAgbGF5b3V0Wyd0ZXh0LWp1c3RpZnknXSA9PT0gJ2xlZnQnID8gMCA6XG4gICAgICAgIDAuNTtcblxuICAgIHZhciBvbmVFbSA9IDI0O1xuICAgIHZhciBsaW5lSGVpZ2h0ID0gbGF5b3V0Wyd0ZXh0LWxpbmUtaGVpZ2h0J10gKiBvbmVFbTtcbiAgICB2YXIgbWF4V2lkdGggPSBsYXlvdXRbJ3N5bWJvbC1wbGFjZW1lbnQnXSAhPT0gJ2xpbmUnID8gbGF5b3V0Wyd0ZXh0LW1heC13aWR0aCddICogb25lRW0gOiAwO1xuICAgIHZhciBzcGFjaW5nID0gbGF5b3V0Wyd0ZXh0LWxldHRlci1zcGFjaW5nJ10gKiBvbmVFbTtcbiAgICB2YXIgdGV4dE9mZnNldCA9IFtsYXlvdXRbJ3RleHQtb2Zmc2V0J11bMF0gKiBvbmVFbSwgbGF5b3V0Wyd0ZXh0LW9mZnNldCddWzFdICogb25lRW1dO1xuICAgIHZhciBmb250c3RhY2sgPSBsYXlvdXRbJ3RleHQtZm9udCddO1xuXG4gICAgdmFyIGdlb21ldHJpZXMgPSBbXTtcbiAgICBmb3IgKHZhciBnID0gMDsgZyA8IGZlYXR1cmVzLmxlbmd0aDsgZysrKSB7XG4gICAgICAgIGdlb21ldHJpZXMucHVzaChmZWF0dXJlc1tnXS5sb2FkR2VvbWV0cnkoKSk7XG4gICAgfVxuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgLy8gTWVyZ2UgYWRqYWNlbnQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IHRvIGltcHJvdmUgbGFiZWxsaW5nLlxuICAgICAgICAvLyBJdCdzIGJldHRlciB0byBwbGFjZSBsYWJlbHMgb24gb25lIGxvbmcgbGluZSB0aGFuIG9uIG1hbnkgc2hvcnQgc2VnbWVudHMuXG4gICAgICAgIHZhciBtZXJnZWQgPSBtZXJnZUxpbmVzKGZlYXR1cmVzLCB0ZXh0RmVhdHVyZXMsIGdlb21ldHJpZXMpO1xuXG4gICAgICAgIGdlb21ldHJpZXMgPSBtZXJnZWQuZ2VvbWV0cmllcztcbiAgICAgICAgZmVhdHVyZXMgPSBtZXJnZWQuZmVhdHVyZXM7XG4gICAgICAgIHRleHRGZWF0dXJlcyA9IG1lcmdlZC50ZXh0RmVhdHVyZXM7XG4gICAgfVxuXG4gICAgdmFyIHNoYXBlZFRleHQsIHNoYXBlZEljb247XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGlmICghZ2VvbWV0cmllc1trXSkgY29udGludWU7XG5cbiAgICAgICAgaWYgKHRleHRGZWF0dXJlc1trXSkge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IHNoYXBlVGV4dCh0ZXh0RmVhdHVyZXNba10sIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10sIG1heFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBsaW5lSGVpZ2h0LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIGp1c3RpZnksIHNwYWNpbmcsIHRleHRPZmZzZXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkVGV4dCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5b3V0WydpY29uLWltYWdlJ10pIHtcbiAgICAgICAgICAgIHZhciBpY29uTmFtZSA9IHJlc29sdmVUb2tlbnMoZmVhdHVyZXNba10ucHJvcGVydGllcywgbGF5b3V0WydpY29uLWltYWdlJ10pO1xuICAgICAgICAgICAgdmFyIGltYWdlID0gdGhpcy5pY29uc1tpY29uTmFtZV07XG4gICAgICAgICAgICBzaGFwZWRJY29uID0gc2hhcGVJY29uKGltYWdlLCBsYXlvdXQpO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZGZJY29ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2RmSWNvbnMgPSBpbWFnZS5zZGY7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNkZkljb25zICE9PSBpbWFnZS5zZGYpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdTdHlsZSBzaGVldCB3YXJuaW5nOiBDYW5ub3QgbWl4IFNERiBhbmQgbm9uLVNERiBpY29ucyBpbiBvbmUgYnVja2V0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2hhcGVkSWNvbiA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hhcGVkVGV4dCB8fCBzaGFwZWRJY29uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEZlYXR1cmUoZ2VvbWV0cmllc1trXSwgc2hhcGVkVGV4dCwgc2hhcGVkSWNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnBsYWNlRmVhdHVyZXModGhpcy5idWZmZXJzLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uKGxpbmVzLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0UHJvcGVydGllcztcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICB2YXIgZ2x5cGhTaXplID0gMjQ7XG5cbiAgICB2YXIgZm9udFNjYWxlID0gbGF5b3V0Wyd0ZXh0LW1heC1zaXplJ10gLyBnbHlwaFNpemUsXG4gICAgICAgIHRleHRCb3hTY2FsZSA9IGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyAqIGZvbnRTY2FsZSxcbiAgICAgICAgaWNvbkJveFNjYWxlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydpY29uLW1heC1zaXplJ10sXG4gICAgICAgIHN5bWJvbE1pbkRpc3RhbmNlID0gY29sbGlzaW9uLnRpbGVQaXhlbFJhdGlvICogbGF5b3V0WydzeW1ib2wtbWluLWRpc3RhbmNlJ10sXG4gICAgICAgIGF2b2lkRWRnZXMgPSBsYXlvdXRbJ3N5bWJvbC1hdm9pZC1lZGdlcyddLFxuICAgICAgICB0ZXh0UGFkZGluZyA9IGxheW91dFsndGV4dC1wYWRkaW5nJ10gKiBjb2xsaXNpb24udGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIGljb25QYWRkaW5nID0gbGF5b3V0WydpY29uLXBhZGRpbmcnXSAqIGNvbGxpc2lvbi50aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdGV4dE1heEFuZ2xlID0gbGF5b3V0Wyd0ZXh0LW1heC1hbmdsZSddIC8gMTgwICogTWF0aC5QSSxcbiAgICAgICAgdGV4dEFsb25nTGluZSA9IGxheW91dFsndGV4dC1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgaWNvbkFsb25nTGluZSA9IGxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9PT0gJ21hcCcgJiYgbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyxcbiAgICAgICAgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICAgICAgbGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddO1xuXG4gICAgaWYgKGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZScpIHtcbiAgICAgICAgbGluZXMgPSBjbGlwTGluZShsaW5lcywgMCwgMCwgNDA5NiwgNDA5Nik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYW5jaG9yIHBvaW50cyBhcm91bmQgd2hpY2ggeW91IHdhbnQgdG8gcGxhY2UgbGFiZWxzXG4gICAgICAgIHZhciBhbmNob3JzID0gbGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJyA/XG4gICAgICAgICAgICBnZXRBbmNob3JzKGxpbmUsIHN5bWJvbE1pbkRpc3RhbmNlLCB0ZXh0TWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgdGV4dEJveFNjYWxlLCB0aGlzLm92ZXJzY2FsaW5nKSA6XG4gICAgICAgICAgICBbIG5ldyBBbmNob3IobGluZVswXS54LCBsaW5lWzBdLnksIDApIF07XG5cbiAgICAgICAgLy8gRm9yIGVhY2ggcG90ZW50aWFsIGxhYmVsLCBjcmVhdGUgdGhlIHBsYWNlbWVudCBmZWF0dXJlcyB1c2VkIHRvIGNoZWNrIGZvciBjb2xsaXNpb25zLCBhbmQgdGhlIHF1YWRzIHVzZSBmb3IgcmVuZGVyaW5nLlxuICAgICAgICBmb3IgKHZhciBqID0gMCwgbGVuID0gYW5jaG9ycy5sZW5ndGg7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgdmFyIGFuY2hvciA9IGFuY2hvcnNbal07XG5cbiAgICAgICAgICAgIHZhciBpbnNpZGUgPSAhKGFuY2hvci54IDwgMCB8fCBhbmNob3IueCA+IDQwOTYgfHwgYW5jaG9yLnkgPCAwIHx8IGFuY2hvci55ID4gNDA5Nik7XG5cbiAgICAgICAgICAgIGlmIChhdm9pZEVkZ2VzICYmICFpbnNpZGUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBOb3JtYWxseSBzeW1ib2wgbGF5ZXJzIGFyZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBPbmx5IHN5bWJvbHNcbiAgICAgICAgICAgIC8vIHdpdGggdGhlaXIgYW5jaG9ycyB3aXRoaW4gdGhlIHRpbGUgYm91bmRhcmllcyBhcmUgYWRkZWQgdG8gdGhlIGJ1ZmZlcnNcbiAgICAgICAgICAgIC8vIHRvIHByZXZlbnQgc3ltYm9scyBmcm9tIGJlaW5nIGRyYXduIHR3aWNlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFN5bWJvbHMgaW4gbGF5ZXJzIHdpdGggb3ZlcmxhcCBhcmUgc29ydGVkIGluIHRoZSB5IGRpcmVjdGlvbiBzbyB0aGF0XG4gICAgICAgICAgICAvLyBzeW1ib2xzIGxvd2VyIG9uIHRoZSBjYW52YXMgYXJlIGRyYXduIG9uIHRvcCBvZiBzeW1ib2xzIG5lYXIgdGhlIHRvcC5cbiAgICAgICAgICAgIC8vIFRvIHByZXNlcnZlIHRoaXMgb3JkZXIgYWNyb3NzIHRpbGUgYm91bmRhcmllcyB0aGVzZSBzeW1ib2xzIGNhbid0XG4gICAgICAgICAgICAvLyBiZSBkcmF3biBhY3Jvc3MgdGlsZSBib3VuZGFyaWVzLiBJbnN0ZWFkIHRoZXkgbmVlZCB0byBiZSBpbmNsdWRlZCBpblxuICAgICAgICAgICAgLy8gdGhlIGJ1ZmZlcnMgZm9yIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgdG8gdGlsZSBib3VuZGFyaWVzIGF0IGRyYXcgdGltZS5cbiAgICAgICAgICAgIHZhciBhZGRUb0J1ZmZlcnMgPSBpbnNpZGUgfHwgbWF5T3ZlcmxhcDtcblxuICAgICAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMucHVzaChuZXcgU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLnBsYWNlRmVhdHVyZXMgPSBmdW5jdGlvbihidWZmZXJzLCBjb2xsaXNpb25EZWJ1Zykge1xuXG4gICAgLy8gQ2FsY3VsYXRlIHdoaWNoIGxhYmVscyBjYW4gYmUgc2hvd24gYW5kIHdoZW4gdGhleSBjYW4gYmUgc2hvd24gYW5kXG4gICAgLy8gY3JlYXRlIHRoZSBidWZlcnMgdXNlZCBmb3IgcmVuZGVyaW5nLlxuXG4gICAgdGhpcy5idWZmZXJzID0gYnVmZmVycztcblxuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGhpcy5lbGVtZW50R3JvdXBzID0ge1xuICAgICAgICB0ZXh0OiBuZXcgRWxlbWVudEdyb3VwcyhidWZmZXJzLmdseXBoVmVydGV4LCBidWZmZXJzLmdseXBoRWxlbWVudCksXG4gICAgICAgIGljb246IG5ldyBFbGVtZW50R3JvdXBzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCksXG4gICAgICAgIHNkZkljb25zOiB0aGlzLnNkZkljb25zXG4gICAgfTtcblxuICAgIHZhciBsYXlvdXQgPSB0aGlzLmxheW91dFByb3BlcnRpZXM7XG4gICAgdmFyIGNvbGxpc2lvbiA9IHRoaXMuY29sbGlzaW9uO1xuICAgIHZhciBtYXhTY2FsZSA9IHRoaXMuY29sbGlzaW9uLm1heFNjYWxlO1xuXG4gICAgdmFyIHRleHRBbG9uZ0xpbmUgPSBsYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG4gICAgdmFyIGljb25BbG9uZ0xpbmUgPSBsYXlvdXRbJ2ljb24tcm90YXRpb24tYWxpZ25tZW50J10gPT09ICdtYXAnICYmIGxheW91dFsnc3ltYm9sLXBsYWNlbWVudCddID09PSAnbGluZSc7XG5cbiAgICB2YXIgbWF5T3ZlcmxhcCA9IGxheW91dFsndGV4dC1hbGxvdy1vdmVybGFwJ10gfHwgbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSB8fFxuICAgICAgICBsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddIHx8IGxheW91dFsnaWNvbi1pZ25vcmUtcGxhY2VtZW50J107XG5cbiAgICAvLyBTb3J0IHN5bWJvbHMgYnkgdGhlaXIgeSBwb3NpdGlvbiBvbiB0aGUgY2FudmFzIHNvIHRoYXQgdGhleSBsb3dlciBzeW1ib2xzXG4gICAgLy8gYXJlIGRyYXduIG9uIHRvcCBvZiBoaWdoZXIgc3ltYm9scy5cbiAgICAvLyBEb24ndCBzb3J0IHN5bWJvbHMgdGhhdCB3b24ndCBvdmVybGFwIGJlY2F1c2UgaXQgaXNuJ3QgbmVjZXNzYXJ5IGFuZFxuICAgIC8vIGJlY2F1c2UgaXQgY2F1c2VzIG1vcmUgbGFiZWxzIHRvIHBvcCBpbiBhbmQgb3V0IHdoZW4gcm90YXRpbmcuXG4gICAgaWYgKG1heU92ZXJsYXApIHtcbiAgICAgICAgdmFyIGFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGU7XG4gICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICBjb3MgPSBNYXRoLmNvcyhhbmdsZSk7XG5cbiAgICAgICAgdGhpcy5zeW1ib2xJbnN0YW5jZXMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICB2YXIgYVJvdGF0ZWQgPSBzaW4gKiBhLnggKyBjb3MgKiBhLnk7XG4gICAgICAgICAgICB2YXIgYlJvdGF0ZWQgPSBzaW4gKiBiLnggKyBjb3MgKiBiLnk7XG4gICAgICAgICAgICByZXR1cm4gYlJvdGF0ZWQgLSBhUm90YXRlZDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgcCA9IDA7IHAgPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IHArKykge1xuICAgICAgICB2YXIgc3ltYm9sSW5zdGFuY2UgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1twXTtcbiAgICAgICAgdmFyIGhhc1RleHQgPSBzeW1ib2xJbnN0YW5jZS5oYXNUZXh0O1xuICAgICAgICB2YXIgaGFzSWNvbiA9IHN5bWJvbEluc3RhbmNlLmhhc0ljb247XG5cbiAgICAgICAgdmFyIGljb25XaXRob3V0VGV4dCA9IGxheW91dFsndGV4dC1vcHRpb25hbCddIHx8ICFoYXNUZXh0LFxuICAgICAgICAgICAgdGV4dFdpdGhvdXRJY29uID0gbGF5b3V0WydpY29uLW9wdGlvbmFsJ10gfHwgIWhhc0ljb247XG5cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNjYWxlcyBhdCB3aGljaCB0aGUgdGV4dCBhbmQgaWNvbiBjYW4gYmUgcGxhY2VkIHdpdGhvdXQgY29sbGlzaW9uLlxuXG4gICAgICAgIHZhciBnbHlwaFNjYWxlID0gaGFzVGV4dCAmJiAhbGF5b3V0Wyd0ZXh0LWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLnRleHRDb2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuICAgICAgICB2YXIgaWNvblNjYWxlID0gaGFzSWNvbiAmJiAhbGF5b3V0WydpY29uLWFsbG93LW92ZXJsYXAnXSA/XG4gICAgICAgICAgICBjb2xsaXNpb24ucGxhY2VGZWF0dXJlKHN5bWJvbEluc3RhbmNlLmljb25Db2xsaXNpb25GZWF0dXJlKSA6IGNvbGxpc2lvbi5taW5TY2FsZTtcblxuXG4gICAgICAgIC8vIENvbWJpbmUgdGhlIHNjYWxlcyBmb3IgaWNvbnMgYW5kIHRleHQuXG5cbiAgICAgICAgaWYgKCFpY29uV2l0aG91dFRleHQgJiYgIXRleHRXaXRob3V0SWNvbikge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gZ2x5cGhTY2FsZSA9IE1hdGgubWF4KGljb25TY2FsZSwgZ2x5cGhTY2FsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRleHRXaXRob3V0SWNvbiAmJiBnbHlwaFNjYWxlKSB7XG4gICAgICAgICAgICBnbHlwaFNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfSBlbHNlIGlmICghaWNvbldpdGhvdXRUZXh0ICYmIGljb25TY2FsZSkge1xuICAgICAgICAgICAgaWNvblNjYWxlID0gTWF0aC5tYXgoaWNvblNjYWxlLCBnbHlwaFNjYWxlKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgLy8gSW5zZXJ0IGZpbmFsIHBsYWNlbWVudCBpbnRvIGNvbGxpc2lvbiB0cmVlIGFuZCBhZGQgZ2x5cGhzL2ljb25zIHRvIGJ1ZmZlcnNcblxuICAgICAgICBpZiAoaGFzVGV4dCkge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ3RleHQtaWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UudGV4dENvbGxpc2lvbkZlYXR1cmUsIGdseXBoU2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdseXBoU2NhbGUgPD0gbWF4U2NhbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFN5bWJvbHMoYnVmZmVycy5nbHlwaFZlcnRleCwgYnVmZmVycy5nbHlwaEVsZW1lbnQsIGVsZW1lbnRHcm91cHMudGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJvbEluc3RhbmNlLmdseXBoUXVhZHMsIGdseXBoU2NhbGUsIGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXSwgdGV4dEFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzSWNvbikge1xuICAgICAgICAgICAgaWYgKCFsYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKSB7XG4gICAgICAgICAgICAgICAgY29sbGlzaW9uLmluc2VydEZlYXR1cmUoc3ltYm9sSW5zdGFuY2UuaWNvbkNvbGxpc2lvbkZlYXR1cmUsIGljb25TY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaWNvblNjYWxlIDw9IG1heFNjYWxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTeW1ib2xzKGJ1ZmZlcnMuaWNvblZlcnRleCwgYnVmZmVycy5pY29uRWxlbWVudCwgZWxlbWVudEdyb3Vwcy5pY29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3ltYm9sSW5zdGFuY2UuaWNvblF1YWRzLCBpY29uU2NhbGUsIGxheW91dFsnaWNvbi1rZWVwLXVwcmlnaHQnXSwgaWNvbkFsb25nTGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGlmIChjb2xsaXNpb25EZWJ1ZykgdGhpcy5hZGRUb0RlYnVnQnVmZmVycygpO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRTeW1ib2xzID0gZnVuY3Rpb24odmVydGV4LCBlbGVtZW50LCBlbGVtZW50R3JvdXBzLCBxdWFkcywgc2NhbGUsIGtlZXBVcHJpZ2h0LCBhbG9uZ0xpbmUpIHtcblxuICAgIGVsZW1lbnRHcm91cHMubWFrZVJvb21Gb3IoNCAqIHF1YWRzLmxlbmd0aCk7XG4gICAgdmFyIGVsZW1lbnRHcm91cCA9IGVsZW1lbnRHcm91cHMuY3VycmVudDtcblxuICAgIHZhciB6b29tID0gdGhpcy5jb2xsaXNpb24uem9vbTtcbiAgICB2YXIgcGxhY2VtZW50Wm9vbSA9IE1hdGgubWF4KE1hdGgubG9nKHNjYWxlKSAvIE1hdGguTE4yICsgem9vbSwgMCk7XG4gICAgdmFyIHBsYWNlbWVudEFuZ2xlID0gdGhpcy5jb2xsaXNpb24uYW5nbGUgKyBNYXRoLlBJO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBxdWFkcy5sZW5ndGg7IGsrKykge1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBxdWFkc1trXSxcbiAgICAgICAgICAgIGFuZ2xlID0gc3ltYm9sLmFuZ2xlO1xuXG4gICAgICAgIC8vIGRyb3AgdXBzaWRlIGRvd24gdmVyc2lvbnMgb2YgZ2x5cGhzXG4gICAgICAgIHZhciBhID0gKGFuZ2xlICsgcGxhY2VtZW50QW5nbGUpICUgKE1hdGguUEkgKiAyKTtcbiAgICAgICAgaWYgKGtlZXBVcHJpZ2h0ICYmIGFsb25nTGluZSAmJiAoYSA8PSBNYXRoLlBJIC8gMiB8fCBhID4gTWF0aC5QSSAqIDMgLyAyKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIHRsID0gc3ltYm9sLnRsLFxuICAgICAgICAgICAgdHIgPSBzeW1ib2wudHIsXG4gICAgICAgICAgICBibCA9IHN5bWJvbC5ibCxcbiAgICAgICAgICAgIGJyID0gc3ltYm9sLmJyLFxuICAgICAgICAgICAgdGV4ID0gc3ltYm9sLnRleCxcbiAgICAgICAgICAgIGFuY2hvciA9IHN5bWJvbC5hbmNob3IsXG5cbiAgICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heCh6b29tICsgTWF0aC5sb2coc3ltYm9sLm1pblNjYWxlKSAvIE1hdGguTE4yLCBwbGFjZW1lbnRab29tKSxcbiAgICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbih6b29tICsgTWF0aC5sb2coc3ltYm9sLm1heFNjYWxlKSAvIE1hdGguTE4yLCAyNSk7XG5cbiAgICAgICAgaWYgKG1heFpvb20gPD0gbWluWm9vbSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTG93ZXIgbWluIHpvb20gc28gdGhhdCB3aGlsZSBmYWRpbmcgb3V0IHRoZSBsYWJlbCBpdCBjYW4gYmUgc2hvd24gb3V0c2lkZSBvZiBjb2xsaXNpb24tZnJlZSB6b29tIGxldmVsc1xuICAgICAgICBpZiAobWluWm9vbSA9PT0gcGxhY2VtZW50Wm9vbSkgbWluWm9vbSA9IDA7XG5cbiAgICAgICAgdmFyIHRyaWFuZ2xlSW5kZXggPSB2ZXJ0ZXguaW5kZXggLSBlbGVtZW50R3JvdXAudmVydGV4U3RhcnRJbmRleDtcblxuICAgICAgICB2ZXJ0ZXguYWRkKGFuY2hvci54LCBhbmNob3IueSwgdGwueCwgdGwueSwgdGV4LngsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIHRyLngsIHRyLnksIHRleC54ICsgdGV4LncsIHRleC55LCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJsLngsIGJsLnksIHRleC54LCB0ZXgueSArIHRleC5oLCBtaW5ab29tLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgdmVydGV4LmFkZChhbmNob3IueCwgYW5jaG9yLnksIGJyLngsIGJyLnksIHRleC54ICsgdGV4LncsIHRleC55ICsgdGV4LmgsIG1pblpvb20sIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICBlbGVtZW50R3JvdXAudmVydGV4TGVuZ3RoICs9IDQ7XG5cbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCwgdHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyKTtcbiAgICAgICAgZWxlbWVudC5hZGQodHJpYW5nbGVJbmRleCArIDEsIHRyaWFuZ2xlSW5kZXggKyAyLCB0cmlhbmdsZUluZGV4ICsgMyk7XG4gICAgICAgIGVsZW1lbnRHcm91cC5lbGVtZW50TGVuZ3RoICs9IDI7XG4gICAgfVxuXG59O1xuXG5TeW1ib2xCdWNrZXQucHJvdG90eXBlLmdldERlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIHZhciBmaXJzdGRvbmUgPSBmYWxzZTtcbiAgICB0aGlzLmdldFRleHREZXBlbmRlbmNpZXModGlsZSwgYWN0b3IsIGRvbmUpO1xuICAgIHRoaXMuZ2V0SWNvbkRlcGVuZGVuY2llcyh0aWxlLCBhY3RvciwgZG9uZSk7XG4gICAgZnVuY3Rpb24gZG9uZShlcnIpIHtcbiAgICAgICAgaWYgKGVyciB8fCBmaXJzdGRvbmUpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICBmaXJzdGRvbmUgPSB0cnVlO1xuICAgIH1cbn07XG5cblN5bWJvbEJ1Y2tldC5wcm90b3R5cGUuZ2V0SWNvbkRlcGVuZGVuY2llcyA9IGZ1bmN0aW9uKHRpbGUsIGFjdG9yLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmxheW91dFByb3BlcnRpZXNbJ2ljb24taW1hZ2UnXSkge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzO1xuICAgICAgICB2YXIgaWNvbnMgPSByZXNvbHZlSWNvbnMoZmVhdHVyZXMsIHRoaXMubGF5b3V0UHJvcGVydGllcyk7XG5cbiAgICAgICAgaWYgKGljb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgYWN0b3Iuc2VuZCgnZ2V0IGljb25zJywgeyBpY29uczogaWNvbnMgfSwgc2V0SWNvbnMuYmluZCh0aGlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRJY29ucyhlcnIsIG5ld2ljb25zKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB0aGlzLmljb25zID0gbmV3aWNvbnM7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5nZXRUZXh0RGVwZW5kZW5jaWVzID0gZnVuY3Rpb24odGlsZSwgYWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlcztcbiAgICB2YXIgZm9udHN0YWNrID0gdGhpcy5sYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZvbnQnXTtcblxuICAgIHZhciBzdGFja3MgPSB0aGlzLnN0YWNrcyA9IHRpbGUuc3RhY2tzO1xuICAgIGlmIChzdGFja3NbZm9udHN0YWNrXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN0YWNrc1tmb250c3RhY2tdID0ge307XG4gICAgfVxuICAgIHZhciBzdGFjayA9IHN0YWNrc1tmb250c3RhY2tdO1xuXG4gICAgdmFyIGRhdGEgPSByZXNvbHZlVGV4dChmZWF0dXJlcywgdGhpcy5sYXlvdXRQcm9wZXJ0aWVzLCBzdGFjayk7XG4gICAgdGhpcy50ZXh0RmVhdHVyZXMgPSBkYXRhLnRleHRGZWF0dXJlcztcblxuICAgIGFjdG9yLnNlbmQoJ2dldCBnbHlwaHMnLCB7XG4gICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgIGZvbnRzdGFjazogZm9udHN0YWNrLFxuICAgICAgICBjb2RlcG9pbnRzOiBkYXRhLmNvZGVwb2ludHNcbiAgICB9LCBmdW5jdGlvbihlcnIsIG5ld3N0YWNrKSB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgIGZvciAodmFyIGNvZGVwb2ludCBpbiBuZXdzdGFjaykge1xuICAgICAgICAgICAgc3RhY2tbY29kZXBvaW50XSA9IG5ld3N0YWNrW2NvZGVwb2ludF07XG4gICAgICAgIH1cblxuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xufTtcblxuU3ltYm9sQnVja2V0LnByb3RvdHlwZS5hZGRUb0RlYnVnQnVmZmVycyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveCA9IG5ldyBFbGVtZW50R3JvdXBzKHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXgpO1xuICAgIHRoaXMuZWxlbWVudEdyb3Vwcy5jb2xsaXNpb25Cb3gubWFrZVJvb21Gb3IoMCk7XG4gICAgdmFyIGJ1ZmZlciA9IHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIGFuZ2xlID0gLXRoaXMuY29sbGlzaW9uLmFuZ2xlO1xuICAgIHZhciB5U3RyZXRjaCA9IHRoaXMuY29sbGlzaW9uLnlTdHJldGNoO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZlYXR1cmUgPSB0aGlzLnN5bWJvbEluc3RhbmNlc1tqXVtpID09PSAwID8gJ3RleHRDb2xsaXNpb25GZWF0dXJlJyA6ICdpY29uQ29sbGlzaW9uRmVhdHVyZSddO1xuICAgICAgICAgICAgaWYgKCFmZWF0dXJlKSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBib3hlcyA9IGZlYXR1cmUuYm94ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwOyBiIDwgYm94ZXMubGVuZ3RoOyBiKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYm94ID0gYm94ZXNbYl07XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IGJveC5hbmNob3I7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGwgPSBuZXcgUG9pbnQoYm94LngxLCBib3gueTEgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG4gICAgICAgICAgICAgICAgdmFyIHRyID0gbmV3IFBvaW50KGJveC54MiwgYm94LnkxICogeVN0cmV0Y2gpLl9yb3RhdGUoYW5nbGUpO1xuICAgICAgICAgICAgICAgIHZhciBibCA9IG5ldyBQb2ludChib3gueDEsIGJveC55MiAqIHlTdHJldGNoKS5fcm90YXRlKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICB2YXIgYnIgPSBuZXcgUG9pbnQoYm94LngyLCBib3gueTIgKiB5U3RyZXRjaCkuX3JvdGF0ZShhbmdsZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4Wm9vbSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDI1LCB0aGlzLmNvbGxpc2lvbi56b29tICsgTWF0aC5sb2coYm94Lm1heFNjYWxlKSAvIE1hdGguTE4yKSk7XG4gICAgICAgICAgICAgICAgdmFyIHBsYWNlbWVudFpvb20gPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNSwgdGhpcy5jb2xsaXNpb24uem9vbSArIE1hdGgubG9nKGJveC5wbGFjZW1lbnRTY2FsZSkgLyBNYXRoLkxOMikpO1xuXG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIHRsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdHIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCB0ciwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJyLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgYnIsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hZGQoYW5jaG9yLCBibCwgbWF4Wm9vbSwgcGxhY2VtZW50Wm9vbSk7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFkZChhbmNob3IsIGJsLCBtYXhab29tLCBwbGFjZW1lbnRab29tKTtcbiAgICAgICAgICAgICAgICBidWZmZXIuYWRkKGFuY2hvciwgdGwsIG1heFpvb20sIHBsYWNlbWVudFpvb20pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzLmNvbGxpc2lvbkJveC5jdXJyZW50LnZlcnRleExlbmd0aCArPSA4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gU3ltYm9sSW5zdGFuY2UoYW5jaG9yLCBsaW5lLCBzaGFwZWRUZXh0LCBzaGFwZWRJY29uLCBsYXlvdXQsIGFkZFRvQnVmZmVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQm94U2NhbGUsIGljb25QYWRkaW5nLCBpY29uQWxvbmdMaW5lKSB7XG5cbiAgICB0aGlzLnggPSBhbmNob3IueDtcbiAgICB0aGlzLnkgPSBhbmNob3IueTtcbiAgICB0aGlzLmhhc1RleHQgPSAhIXNoYXBlZFRleHQ7XG4gICAgdGhpcy5oYXNJY29uID0gISFzaGFwZWRJY29uO1xuXG4gICAgaWYgKHRoaXMuaGFzVGV4dCkge1xuICAgICAgICB0aGlzLmdseXBoUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRHbHlwaFF1YWRzKGFuY2hvciwgc2hhcGVkVGV4dCwgdGV4dEJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIHRleHRBbG9uZ0xpbmUpIDogW107XG4gICAgICAgIHRoaXMudGV4dENvbGxpc2lvbkZlYXR1cmUgPSBuZXcgQ29sbGlzaW9uRmVhdHVyZShsaW5lLCBhbmNob3IsIHNoYXBlZFRleHQsIHRleHRCb3hTY2FsZSwgdGV4dFBhZGRpbmcsIHRleHRBbG9uZ0xpbmUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0ljb24pIHtcbiAgICAgICAgdGhpcy5pY29uUXVhZHMgPSBhZGRUb0J1ZmZlcnMgPyBnZXRJY29uUXVhZHMoYW5jaG9yLCBzaGFwZWRJY29uLCBpY29uQm94U2NhbGUsIGxpbmUsIGxheW91dCwgaWNvbkFsb25nTGluZSkgOiBbXTtcbiAgICAgICAgdGhpcy5pY29uQ29sbGlzaW9uRmVhdHVyZSA9IG5ldyBDb2xsaXNpb25GZWF0dXJlKGxpbmUsIGFuY2hvciwgc2hhcGVkSWNvbiwgaWNvbkJveFNjYWxlLCBpY29uUGFkZGluZywgaWNvbkFsb25nTGluZSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvb3JkaW5hdGU7XG5cbi8qKlxuICogQSBjb29yZGluYXRlIGlzIGEgY29sdW1uLCByb3csIHpvb20gY29tYmluYXRpb24sIG9mdGVuIHVzZWRcbiAqIGFzIHRoZSBkYXRhIGNvbXBvbmVudCBvZiBhIHRpbGUuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IGNvbHVtblxuICogQHBhcmFtIHtOdW1iZXJ9IHJvd1xuICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIENvb3JkaW5hdGUoY29sdW1uLCByb3csIHpvb20pIHtcbiAgICB0aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICB0aGlzLnJvdyA9IHJvdztcbiAgICB0aGlzLnpvb20gPSB6b29tO1xufVxuXG5Db29yZGluYXRlLnByb3RvdHlwZSA9IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGNsb25lIG9mIHRoaXMgY29vcmRpbmF0ZSB0aGF0IGNhbiBiZSBtdXRhdGVkIHdpdGhvdXRcbiAgICAgKiBjaGFuZ2luZyB0aGUgb3JpZ2luYWwgY29vcmRpbmF0ZVxuICAgICAqXG4gICAgICogQHJldHVybnMge0Nvb3JkaW5hdGV9IGNsb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC5jbG9uZSgpO1xuICAgICAqIC8vIHNpbmNlIGNvb3JkIGlzIGNsb25lZCwgbW9kaWZ5aW5nIGEgcHJvcGVydHkgb2YgYzIgZG9lc1xuICAgICAqIC8vIG5vdCBtb2RpZnkgaXQuXG4gICAgICogYzIuem9vbSA9IDI7XG4gICAgICovXG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUodGhpcy5jb2x1bW4sIHRoaXMucm93LCB0aGlzLnpvb20pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIHRoaXMgY29vcmRpbmF0ZSB0byBhIGdpdmVuIHpvb20gbGV2ZWwuIFRoaXMgcmV0dXJucyBhIG5ld1xuICAgICAqIGNvb3JkaW5hdGUgb2JqZWN0LCBub3QgbXV0YXRpbmcgdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gem9vbVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSB6b29tZWQgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiB2YXIgY29vcmQgPSBuZXcgQ29vcmRpbmF0ZSgwLCAwLCAwKTtcbiAgICAgKiB2YXIgYzIgPSBjb29yZC56b29tVG8oMSk7XG4gICAgICogYzIgLy8gZXF1YWxzIG5ldyBDb29yZGluYXRlKDAsIDAsIDEpO1xuICAgICAqL1xuICAgIHpvb21UbzogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl96b29tVG8oem9vbSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTdWJ0cmFjdCB0aGUgY29sdW1uIGFuZCByb3cgdmFsdWVzIG9mIHRoaXMgY29vcmRpbmF0ZSBmcm9tIHRob3NlXG4gICAgICogb2YgYW5vdGhlciBjb29yZGluYXRlLiBUaGUgb3RoZXIgY29vcmRpbmF0IHdpbGwgYmUgem9vbWVkIHRvIHRoZVxuICAgICAqIHNhbWUgbGV2ZWwgYXMgYHRoaXNgIGJlZm9yZSB0aGUgc3VidHJhY3Rpb24gb2NjdXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGMgb3RoZXIgY29vcmRpbmF0ZVxuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfSByZXN1bHRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN1YjogZnVuY3Rpb24oYykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWIoYyk7IH0sXG5cbiAgICBfem9vbVRvOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHZhciBzY2FsZSA9IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAqPSBzY2FsZTtcbiAgICAgICAgdGhpcy5yb3cgKj0gc2NhbGU7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfc3ViOiBmdW5jdGlvbihjKSB7XG4gICAgICAgIGMgPSBjLnpvb21Ubyh0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmNvbHVtbiAtPSBjLmNvbHVtbjtcbiAgICAgICAgdGhpcy5yb3cgLT0gYy5yb3c7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nO1xuXG52YXIgd3JhcCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpLndyYXA7XG5cbi8qKlxuICogQ3JlYXRlIGEgbGF0aXR1ZGUsIGxvbmdpdHVkZSBvYmplY3QgZnJvbSBhIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcGFpciBpbiBkZWdyZWVzLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiBhIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgcG9pbnQsIGluIGRlZ3JlZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gbGF0IGxhdGl0dWRlXG4gKiBAcGFyYW0ge251bWJlcn0gbG5nIGxvbmdpdHVkZVxuICogQGV4YW1wbGVcbiAqIHZhciBsYXRsbmcgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDM3Ljc2LCAtMTIyLjQ0KTtcbiAqL1xuZnVuY3Rpb24gTGF0TG5nKGxhdCwgbG5nKSB7XG4gICAgaWYgKGlzTmFOKGxhdCkgfHwgaXNOYU4obG5nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgTGF0TG5nIG9iamVjdDogKCcgKyBsYXQgKyAnLCAnICsgbG5nICsgJyknKTtcbiAgICB9XG4gICAgdGhpcy5sYXQgPSArbGF0O1xuICAgIHRoaXMubG5nID0gK2xuZztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBuZXcgYExhdExuZ2Agb2JqZWN0IHdob3NlIGxvbmdpdHVkZSBpcyB3cmFwcGVkIHRvIHRoZSByYW5nZSAoLTE4MCwgMTgwKS5cbiAqXG4gKiBAcmV0dXJucyB7TGF0TG5nfSB3cmFwcGVkIExhdExuZyBvYmplY3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9pbnQgPSBtYXBib3hnbC5MYXRMbmcoMCwgMjAwKTtcbiAqIHZhciB3cmFwcGVkID0gcG9pbnQud3JhcCgpO1xuICogd3JhcHBlZC5sbmc7IC8vID0gLTE2MFxuICovXG5MYXRMbmcucHJvdG90eXBlLndyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHdyYXAodGhpcy5sbmcsIC0xODAsIDE4MCkpO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IGFuIGFycmF5IHRvIGEgYExhdExuZ2Agb2JqZWN0LCBvciByZXR1cm4gYW4gZXhpc3RpbmcgYExhdExuZ2Agb2JqZWN0XG4gKiB1bmNoYW5nZWQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fExhdExuZ30gaW5wdXQgYGlucHV0YCB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7TGF0TG5nfSBMYXRMbmcgb2JqZWN0IG9yIG9yaWdpbmFsIGlucHV0XG4gKiBAZXhhbXBsZVxuICogdmFyIGxsID0gbWFwYm94Z2wuTGF0TG5nLmNvbnZlcnQoWzEwLCAxMF0pO1xuICogdmFyIGxsMiA9IG5ldyBtYXBib3hnbC5MYXRMbmcoMTAsIDEwKTtcbiAqIGxsIC8vID0gbGwyXG4gKi9cbkxhdExuZy5jb252ZXJ0ID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKGlucHV0WzBdLCBpbnB1dFsxXSk7XG4gICAgfVxuICAgIHJldHVybiBpbnB1dDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gTGF0TG5nQm91bmRzO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGJvdW5kaW5nIGJveCBmcm9tIHRoZSBnaXZlbiBwYWlyIG9mIHBvaW50cy4gSWYgcGFyYW1ldGVyZXMgYXJlIG9taXR0ZWQsIGEgYG51bGxgIGJvdW5kaW5nIGJveCBpcyBjcmVhdGVkLlxuICpcbiAqIEBjbGFzcyBMYXRMbmdCb3VuZHNcbiAqIEBjbGFzc2Rlc2MgQSByZXByZXNlbnRhdGlvbiBvZiByZWN0YW5ndWxhciBib3ggb24gdGhlIGVhcnRoLCBkZWZpbmVkIGJ5IGl0cyBzb3V0aHdlc3QgYW5kIG5vcnRoZWFzdCBwb2ludHMgaW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS5cbiAqIEBwYXJhbSB7TGF0TG5nfSBzdyBzb3V0aHdlc3RcbiAqIEBwYXJhbSB7TGF0TG5nfSBuZSBub3J0aGVhc3RcbiAqIEBleGFtcGxlXG4gKiB2YXIgc3cgPSBuZXcgbWFwYm94Z2wuTGF0TG5nKDAsIDApO1xuICogdmFyIG5lID0gbmV3IG1hcGJveGdsLkxhdExuZygxMCwgLTEwKTtcbiAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKHN3LCBuZSk7XG4gKlxuICovXG5mdW5jdGlvbiBMYXRMbmdCb3VuZHMoc3csIG5lKSB7XG4gICAgaWYgKCFzdykgcmV0dXJuO1xuXG4gICAgdmFyIGxhdGxuZ3MgPSBuZSA/IFtzdywgbmVdIDogc3c7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB0aGlzLmV4dGVuZChsYXRsbmdzW2ldKTtcbiAgICB9XG59XG5cbkxhdExuZ0JvdW5kcy5wcm90b3R5cGUgPSB7XG5cbiAgICAvKipcbiAgICAgKiBFeHRlbmQgdGhlIGJvdW5kcyB0byBpbmNsdWRlIGEgZ2l2ZW4gTGF0TG5nIG9yIExhdExuZ0JvdW5kcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TGF0TG5nfExhdExuZ0JvdW5kc30gb2JqIG9iamVjdCB0byBleHRlbmQgdG9cbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nQm91bmRzfSBgdGhpc2BcbiAgICAgKi9cbiAgICBleHRlbmQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICB2YXIgc3cgPSB0aGlzLl9zdyxcbiAgICAgICAgICAgIG5lID0gdGhpcy5fbmUsXG4gICAgICAgICAgICBzdzIsIG5lMjtcblxuICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nKSB7XG4gICAgICAgICAgICBzdzIgPSBvYmo7XG4gICAgICAgICAgICBuZTIgPSBvYmo7XG5cbiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcbiAgICAgICAgICAgIHN3MiA9IG9iai5fc3c7XG4gICAgICAgICAgICBuZTIgPSBvYmouX25lO1xuXG4gICAgICAgICAgICBpZiAoIXN3MiB8fCAhbmUyKSByZXR1cm4gdGhpcztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKExhdExuZy5jb252ZXJ0KG9iaikgfHwgTGF0TG5nQm91bmRzLmNvbnZlcnQob2JqKSkgOiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzdyAmJiAhbmUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N3ID0gbmV3IExhdExuZyhzdzIubGF0LCBzdzIubG5nKTtcbiAgICAgICAgICAgIHRoaXMuX25lID0gbmV3IExhdExuZyhuZTIubGF0LCBuZTIubG5nKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcbiAgICAgICAgICAgIHN3LmxuZyA9IE1hdGgubWluKHN3Mi5sbmcsIHN3LmxuZyk7XG4gICAgICAgICAgICBuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xuICAgICAgICAgICAgbmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHBvaW50IGVxdWlkaXN0YW50IGZyb20gdGhpcyBib3gncyBjb3JuZXJzXG4gICAgICogQHJldHVybnMge0xhdExuZ30gY2VudGVycG9pbnRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHZhciBib3VuZHMgPSBuZXcgbWFwYm94Z2wuTGF0TG5nQm91bmRzKFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygxMCwgMTApLFxuICAgICAqICAgbmV3IG1hcGJveGdsLkxhdExuZygtMTAsIC0xMCk7XG4gICAgICogYm91bmRzLmdldENlbnRlcigpOyAvLyBlcXVhbHMgbWFwYm94Z2wuTGF0TG5nKDAsIDApXG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmcoKHRoaXMuX3N3LmxhdCArIHRoaXMuX25lLmxhdCkgLyAyLCAodGhpcy5fc3cubG5nICsgdGhpcy5fbmUubG5nKSAvIDIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGh3ZXN0IGNvcm5lclxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9IHNvdXRod2VzdFxuICAgICAqL1xuICAgIGdldFNvdXRoV2VzdDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdzsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBub3J0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbm9ydGhlYXN0XG4gICAgICovXG4gICAgZ2V0Tm9ydGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRod2VzdCBjb3JuZXJcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBub3J0aHdlc3RcbiAgICAgKi9cbiAgICBnZXROb3J0aFdlc3Q6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IExhdExuZyh0aGlzLmdldE5vcnRoKCksIHRoaXMuZ2V0V2VzdCgpKTsgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBzb3V0aGVhc3QgY29ybmVyXG4gICAgICogQHJldHVybnMge0xhdExuZ30gc291dGhlYXN0XG4gICAgICovXG4gICAgZ2V0U291dGhFYXN0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSk7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgd2VzdCBlZGdlIGxvbmdpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHdlc3RcbiAgICAgKi9cbiAgICBnZXRXZXN0OiAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLl9zdy5sbmc7IH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgc291dGggZWRnZSBsYXRpdHVkZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHNvdXRoXG4gICAgICovXG4gICAgZ2V0U291dGg6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fc3cubGF0OyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IGVhc3QgZWRnZSBsb25naXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBlYXN0XG4gICAgICovXG4gICAgZ2V0RWFzdDogIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5fbmUubG5nOyB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IG5vcnRoIGVkZ2UgbGF0aXR1ZGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBub3J0aFxuICAgICAqL1xuICAgIGdldE5vcnRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuX25lLmxhdDsgfVxufTtcblxuLyoqXG4gKiBjb25zdHJ1Y3RzIExhdExuZ0JvdW5kcyBmcm9tIGFuIGFycmF5IGlmIG5lY2Vzc2FyeVxuICogQHBhcmFtIHtMYXRMbmdCb3VuZHN8Kn0gYSBhbnkgaW5wdXRcbiAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN8ZmFsc2V9XG4gKiBAZXhhbXBsZVxuICogLy8gY2FsbHMgTGF0TG5nLmNvbnZlcnQgaW50ZXJuYWxseSB0b1xuICogLy8gc3VwcG9ydCBhcnJheXMgYXMgbGF0bG5nIHZhbHVlc1xuICogTGF0TG5nQm91bmRzLmNvbnZlcnQoW1stMTAsIC0xMF0sIFsxMCwgMTBdXSk7XG4gKi9cbkxhdExuZ0JvdW5kcy5jb252ZXJ0ID0gZnVuY3Rpb24gKGEpIHtcbiAgICBpZiAoIWEgfHwgYSBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykgcmV0dXJuIGE7XG4gICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi9sYXRfbG5nJyksXG4gICAgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpLFxuICAgIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuL2Nvb3JkaW5hdGUnKSxcbiAgICB3cmFwID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJykud3JhcCxcbiAgICBpbnRlcnAgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyksXG4gICAgdmVjNCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLnZlYzQsXG4gICAgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhbnNmb3JtO1xuXG4vKlxuICogQSBzaW5nbGUgdHJhbnNmb3JtLCBnZW5lcmFsbHkgdXNlZCBmb3IgYSBzaW5nbGUgdGlsZSB0byBiZVxuICogc2NhbGVkLCByb3RhdGVkLCBhbmQgem9vbWVkLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtaW5ab29tXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4Wm9vbVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gVHJhbnNmb3JtKG1pblpvb20sIG1heFpvb20pIHtcbiAgICB0aGlzLnRpbGVTaXplID0gNTEyOyAvLyBjb25zdGFudFxuXG4gICAgdGhpcy5fbWluWm9vbSA9IG1pblpvb20gfHwgMDtcbiAgICB0aGlzLl9tYXhab29tID0gbWF4Wm9vbSB8fCAyMjtcblxuICAgIHRoaXMubGF0UmFuZ2UgPSBbLTg1LjA1MTEzLCA4NS4wNTExM107XG5cbiAgICB0aGlzLndpZHRoID0gMDtcbiAgICB0aGlzLmhlaWdodCA9IDA7XG4gICAgdGhpcy56b29tID0gMDtcbiAgICB0aGlzLmNlbnRlciA9IG5ldyBMYXRMbmcoMCwgMCk7XG4gICAgdGhpcy5hbmdsZSA9IDA7XG4gICAgdGhpcy5fYWx0aXR1ZGUgPSAxLjU7XG4gICAgdGhpcy5fcGl0Y2ggPSAwO1xufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlID0ge1xuICAgIGdldCBtaW5ab29tKCkgeyByZXR1cm4gdGhpcy5fbWluWm9vbTsgfSxcbiAgICBzZXQgbWluWm9vbSh6b29tKSB7XG4gICAgICAgIHRoaXMuX21pblpvb20gPSB6b29tO1xuICAgICAgICB0aGlzLnpvb20gPSBNYXRoLm1heCh0aGlzLnpvb20sIHpvb20pO1xuICAgIH0sXG5cbiAgICBnZXQgbWF4Wm9vbSgpIHsgcmV0dXJuIHRoaXMuX21heFpvb207IH0sXG4gICAgc2V0IG1heFpvb20oem9vbSkge1xuICAgICAgICB0aGlzLl9tYXhab29tID0gem9vbTtcbiAgICAgICAgdGhpcy56b29tID0gTWF0aC5taW4odGhpcy56b29tLCB6b29tKTtcbiAgICB9LFxuXG4gICAgZ2V0IHdvcmxkU2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUgKiB0aGlzLnNjYWxlO1xuICAgIH0sXG5cbiAgICBnZXQgY2VudGVyUG9pbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemUuX2RpdigyKTtcbiAgICB9LFxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xuICAgIH0sXG5cbiAgICBnZXQgYmVhcmluZygpIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLmFuZ2xlIC8gTWF0aC5QSSAqIDE4MDtcbiAgICB9LFxuICAgIHNldCBiZWFyaW5nKGJlYXJpbmcpIHtcbiAgICAgICAgdGhpcy5hbmdsZSA9IC13cmFwKGJlYXJpbmcsIC0xODAsIDE4MCkgKiBNYXRoLlBJIC8gMTgwO1xuICAgIH0sXG5cbiAgICBnZXQgcGl0Y2goKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9waXRjaCAvIE1hdGguUEkgKiAxODA7XG4gICAgfSxcbiAgICBzZXQgcGl0Y2gocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5fcGl0Y2ggPSBNYXRoLm1pbig2MCwgcGl0Y2gpIC8gMTgwICogTWF0aC5QSTtcbiAgICB9LFxuXG4gICAgZ2V0IGFsdGl0dWRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWx0aXR1ZGU7XG4gICAgfSxcbiAgICBzZXQgYWx0aXR1ZGUoYWx0aXR1ZGUpIHtcbiAgICAgICAgdGhpcy5fYWx0aXR1ZGUgPSBNYXRoLm1heCgwLjc1LCBhbHRpdHVkZSk7XG4gICAgfSxcblxuICAgIGdldCB6b29tKCkgeyByZXR1cm4gdGhpcy5fem9vbTsgfSxcbiAgICBzZXQgem9vbSh6b29tKSB7XG4gICAgICAgIHpvb20gPSBNYXRoLm1pbihNYXRoLm1heCh6b29tLCB0aGlzLm1pblpvb20pLCB0aGlzLm1heFpvb20pO1xuICAgICAgICB0aGlzLl96b29tID0gem9vbTtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHRoaXMuem9vbVNjYWxlKHpvb20pO1xuICAgICAgICB0aGlzLnRpbGVab29tID0gTWF0aC5mbG9vcih6b29tKTtcbiAgICAgICAgdGhpcy56b29tRnJhY3Rpb24gPSB6b29tIC0gdGhpcy50aWxlWm9vbTtcbiAgICAgICAgdGhpcy5fY29uc3RyYWluKCk7XG4gICAgfSxcblxuICAgIHpvb21TY2FsZTogZnVuY3Rpb24oem9vbSkgeyByZXR1cm4gTWF0aC5wb3coMiwgem9vbSk7IH0sXG4gICAgc2NhbGVab29tOiBmdW5jdGlvbihzY2FsZSkgeyByZXR1cm4gTWF0aC5sb2coc2NhbGUpIC8gTWF0aC5MTjI7IH0sXG5cbiAgICBwcm9qZWN0OiBmdW5jdGlvbihsYXRsbmcsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IFBvaW50KFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcsIHdvcmxkU2l6ZSksXG4gICAgICAgICAgICB0aGlzLmxhdFkobGF0bG5nLmxhdCwgd29ybGRTaXplKSk7XG4gICAgfSxcblxuICAgIHVucHJvamVjdDogZnVuY3Rpb24ocG9pbnQsIHdvcmxkU2l6ZSkge1xuICAgICAgICByZXR1cm4gbmV3IExhdExuZyhcbiAgICAgICAgICAgIHRoaXMueUxhdChwb2ludC55LCB3b3JsZFNpemUpLFxuICAgICAgICAgICAgdGhpcy54TG5nKHBvaW50LngsIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBnZXQgeCgpIHsgcmV0dXJuIHRoaXMubG5nWCh0aGlzLmNlbnRlci5sbmcpOyB9LFxuICAgIGdldCB5KCkgeyByZXR1cm4gdGhpcy5sYXRZKHRoaXMuY2VudGVyLmxhdCk7IH0sXG5cbiAgICBnZXQgcG9pbnQoKSB7IHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpOyB9LFxuXG4gICAgLyoqXG4gICAgICogbGF0L2xvbiA8LT4gYWJzb2x1dGUgcGl4ZWwgY29vcmRzIGNvbnZlcnNpb25cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbG9uXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG5nWDogZnVuY3Rpb24obG9uLCB3b3JsZFNpemUpIHtcbiAgICAgICAgcmV0dXJuICgxODAgKyBsb24pICogKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLyAzNjA7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBsYXRpdHVkZSB0byBhYnNvbHV0ZSB5IGNvb3JkXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGF0XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3b3JsZFNpemU9dGhpcy53b3JsZFNpemVdXG4gICAgICogQHJldHVybnMge051bWJlcn0gcGl4ZWwgY29vcmRpbmF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbGF0WTogZnVuY3Rpb24obGF0LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkgPSAxODAgLyBNYXRoLlBJICogTWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSSAvIDQgKyBsYXQgKiBNYXRoLlBJIC8gMzYwKSk7XG4gICAgICAgIHJldHVybiAoMTgwIC0geSkgKiAod29ybGRTaXplIHx8IHRoaXMud29ybGRTaXplKSAvIDM2MDtcbiAgICB9LFxuXG4gICAgeExuZzogZnVuY3Rpb24oeCwgd29ybGRTaXplKSB7XG4gICAgICAgIHJldHVybiB4ICogMzYwIC8gKHdvcmxkU2l6ZSB8fCB0aGlzLndvcmxkU2l6ZSkgLSAxODA7XG4gICAgfSxcbiAgICB5TGF0OiBmdW5jdGlvbih5LCB3b3JsZFNpemUpIHtcbiAgICAgICAgdmFyIHkyID0gMTgwIC0geSAqIDM2MCAvICh3b3JsZFNpemUgfHwgdGhpcy53b3JsZFNpemUpO1xuICAgICAgICByZXR1cm4gMzYwIC8gTWF0aC5QSSAqIE1hdGguYXRhbihNYXRoLmV4cCh5MiAqIE1hdGguUEkgLyAxODApKSAtIDkwO1xuICAgIH0sXG5cbiAgICBwYW5CeTogZnVuY3Rpb24ob2Zmc2V0KSB7XG4gICAgICAgIHZhciBwb2ludCA9IHRoaXMuY2VudGVyUG9pbnQuX2FkZChvZmZzZXQpO1xuICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMucG9pbnRMb2NhdGlvbihwb2ludCk7XG4gICAgICAgIHRoaXMuX2NvbnN0cmFpbigpO1xuICAgIH0sXG5cbiAgICBzZXRMb2NhdGlvbkF0UG9pbnQ6IGZ1bmN0aW9uKGxhdGxuZywgcG9pbnQpIHtcbiAgICAgICAgdmFyIGMgPSB0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpO1xuICAgICAgICB2YXIgY29vcmRBdFBvaW50ID0gdGhpcy5wb2ludENvb3JkaW5hdGUocG9pbnQpO1xuICAgICAgICB2YXIgY29vcmRDZW50ZXIgPSB0aGlzLnBvaW50Q29vcmRpbmF0ZSh0aGlzLmNlbnRlclBvaW50KTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlID0gY29vcmRBdFBvaW50Ll9zdWIoYyk7XG4gICAgICAgIHRoaXMuY2VudGVyID0gdGhpcy5jb29yZGluYXRlTG9jYXRpb24oY29vcmRDZW50ZXIuX3N1Yih0cmFuc2xhdGUpKTtcblxuICAgICAgICB0aGlzLl9jb25zdHJhaW4oKTtcbiAgICB9LFxuXG4gICAgc2V0Wm9vbUFyb3VuZDogZnVuY3Rpb24oem9vbSwgY2VudGVyKSB7XG4gICAgICAgIHZhciBwID0gdGhpcy5sb2NhdGlvblBvaW50KGNlbnRlcik7XG4gICAgICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgICAgIHRoaXMuc2V0TG9jYXRpb25BdFBvaW50KGNlbnRlciwgcCk7XG4gICAgfSxcblxuICAgIHNldEJlYXJpbmdBcm91bmQ6IGZ1bmN0aW9uKGJlYXJpbmcsIGNlbnRlcikge1xuICAgICAgICB2YXIgcCA9IHRoaXMubG9jYXRpb25Qb2ludChjZW50ZXIpO1xuICAgICAgICB0aGlzLmJlYXJpbmcgPSBiZWFyaW5nO1xuICAgICAgICB0aGlzLnNldExvY2F0aW9uQXRQb2ludChjZW50ZXIsIHApO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGxvY2F0aW9uLCByZXR1cm4gdGhlIHNjcmVlbiBwb2ludCB0aGF0IGNvcnJlc3BvbmRzIHRvIGl0XG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZyBsb2NhdGlvblxuICAgICAqIEByZXR1cm5zIHtQb2ludH0gc2NyZWVuIHBvaW50XG4gICAgICovXG4gICAgbG9jYXRpb25Qb2ludDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShsYXRsbmcpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBwb2ludCBvbiBzY3JlZW4sIHJldHVybiBpdHMgbGF0bG5nXG4gICAgICogQHBhcmFtIHtQb2ludH0gcCBzY3JlZW4gcG9pbnRcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfSBsYXRsbmcgbG9jYXRpb25cbiAgICAgKi9cbiAgICBwb2ludExvY2F0aW9uOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZShwKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGxhdGxuZywgcmV0dXJuIGFuIHVucm91bmRlZFxuICAgICAqIGNvb3JkaW5hdGUgdGhhdCByZXByZXNlbnRzIGl0IGF0IHRoaXMgdHJhbnNmb3JtJ3Mgem9vbSBsZXZlbCBhbmRcbiAgICAgKiB3b3JsZHNpemUuXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtDb29yZGluYXRlfVxuICAgICAqL1xuICAgIGxvY2F0aW9uQ29vcmRpbmF0ZTogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHZhciBrID0gdGhpcy56b29tU2NhbGUodGhpcy50aWxlWm9vbSkgLyB0aGlzLndvcmxkU2l6ZTtcbiAgICAgICAgcmV0dXJuIG5ldyBDb29yZGluYXRlKFxuICAgICAgICAgICAgdGhpcy5sbmdYKGxhdGxuZy5sbmcpICogayxcbiAgICAgICAgICAgIHRoaXMubGF0WShsYXRsbmcubGF0KSAqIGssXG4gICAgICAgICAgICB0aGlzLnRpbGVab29tKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBDb29yZGluYXRlLCByZXR1cm4gaXRzIGdlb2dyYXBoaWNhbCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHJldHVybnMge0xhdExuZ30gbGF0bG5nXG4gICAgICovXG4gICAgY29vcmRpbmF0ZUxvY2F0aW9uOiBmdW5jdGlvbihjb29yZCkge1xuICAgICAgICB2YXIgd29ybGRTaXplID0gdGhpcy56b29tU2NhbGUoY29vcmQuem9vbSk7XG4gICAgICAgIHJldHVybiBuZXcgTGF0TG5nKFxuICAgICAgICAgICAgdGhpcy55TGF0KGNvb3JkLnJvdywgd29ybGRTaXplKSxcbiAgICAgICAgICAgIHRoaXMueExuZyhjb29yZC5jb2x1bW4sIHdvcmxkU2l6ZSkpO1xuICAgIH0sXG5cbiAgICBwb2ludENvb3JkaW5hdGU6IGZ1bmN0aW9uKHAsIHRhcmdldFopIHtcblxuICAgICAgICBpZiAodGFyZ2V0WiA9PT0gdW5kZWZpbmVkKSB0YXJnZXRaID0gMDtcblxuICAgICAgICB2YXIgbWF0cml4ID0gdGhpcy5jb29yZGluYXRlUG9pbnRNYXRyaXgodGhpcy50aWxlWm9vbSk7XG4gICAgICAgIHZhciBpbnZlcnRlZCA9IG1hdDQuaW52ZXJ0KG5ldyBGbG9hdDY0QXJyYXkoMTYpLCBtYXRyaXgpO1xuXG4gICAgICAgIGlmICghaW52ZXJ0ZWQpIHRocm93IFwiZmFpbGVkIHRvIGludmVydCBtYXRyaXhcIjtcblxuICAgICAgICAvLyBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSBjb3JyZWN0IHByb2plY3RlZCB6IHZhbHVlIGZvciB0aGUgcG9pbnQsXG4gICAgICAgIC8vIHVucHJvamVjdCB0d28gcG9pbnRzIHRvIGdldCBhIGxpbmUgYW5kIHRoZW4gZmluZCB0aGUgcG9pbnQgb24gdGhhdFxuICAgICAgICAvLyBsaW5lIHdpdGggej0wXG5cbiAgICAgICAgdmFyIGNvb3JkMCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW3AueCwgcC55LCAwLCAxXSwgaW52ZXJ0ZWQpO1xuICAgICAgICB2YXIgY29vcmQxID0gdmVjNC50cmFuc2Zvcm1NYXQ0KFtdLCBbcC54LCBwLnksIDEsIDFdLCBpbnZlcnRlZCk7XG5cbiAgICAgICAgdmFyIHcwID0gY29vcmQwWzNdO1xuICAgICAgICB2YXIgdzEgPSBjb29yZDFbM107XG4gICAgICAgIHZhciB4MCA9IGNvb3JkMFswXSAvIHcwO1xuICAgICAgICB2YXIgeDEgPSBjb29yZDFbMF0gLyB3MTtcbiAgICAgICAgdmFyIHkwID0gY29vcmQwWzFdIC8gdzA7XG4gICAgICAgIHZhciB5MSA9IGNvb3JkMVsxXSAvIHcxO1xuICAgICAgICB2YXIgejAgPSBjb29yZDBbMl0gLyB3MDtcbiAgICAgICAgdmFyIHoxID0gY29vcmQxWzJdIC8gdzE7XG5cblxuICAgICAgICB2YXIgdCA9IHowID09PSB6MSA/IDAgOiAodGFyZ2V0WiAtIHowKSAvICh6MSAtIHowKTtcblxuICAgICAgICByZXR1cm4gbmV3IENvb3JkaW5hdGUoXG4gICAgICAgICAgICBpbnRlcnAoeDAsIHgxLCB0KSxcbiAgICAgICAgICAgIGludGVycCh5MCwgeTEsIHQpLFxuICAgICAgICAgICAgdGhpcy50aWxlWm9vbSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgY29vcmRpbmF0ZSwgcmV0dXJuIHRoZSBzY3JlZW4gcG9pbnQgdGhhdCBjb3JyZXNwb25kcyB0byBpdFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7UG9pbnR9IHNjcmVlbiBwb2ludFxuICAgICAqL1xuICAgIGNvb3JkaW5hdGVQb2ludDogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMuY29vcmRpbmF0ZVBvaW50TWF0cml4KGNvb3JkLnpvb20pO1xuICAgICAgICB2YXIgcCA9IHZlYzQudHJhbnNmb3JtTWF0NChbXSwgW2Nvb3JkLmNvbHVtbiwgY29vcmQucm93LCAwLCAxXSwgbWF0cml4KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChwWzBdIC8gcFszXSwgcFsxXSAvIHBbM10pO1xuICAgIH0sXG5cbiAgICBjb29yZGluYXRlUG9pbnRNYXRyaXg6IGZ1bmN0aW9uKHopIHtcbiAgICAgICAgdmFyIHByb2ogPSB0aGlzLmdldFByb2pNYXRyaXgoKTtcbiAgICAgICAgdmFyIHNjYWxlID0gdGhpcy53b3JsZFNpemUgLyB0aGlzLnpvb21TY2FsZSh6KTtcbiAgICAgICAgbWF0NC5zY2FsZShwcm9qLCBwcm9qLCBbc2NhbGUsIHNjYWxlLCAxXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkocHJvaiwgdGhpcy5nZXRQaXhlbE1hdHJpeCgpLCBwcm9qKTtcbiAgICAgICAgcmV0dXJuIHByb2o7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIGNvbnZlcnRzIGdsIGNvb3JkaW5hdGVzIC0xLi4xIHRvIHBpeGVscyAwLi53aWR0aFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IG1hdHJpeFxuICAgICAqL1xuICAgIGdldFBpeGVsTWF0cml4OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG0gPSBtYXQ0LmNyZWF0ZSgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFt0aGlzLndpZHRoIC8gMiwgLXRoaXMuaGVpZ2h0IC8gMiwgMV0pO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbMSwgLTEsIDBdKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgfSxcblxuICAgIF9jb25zdHJhaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VudGVyKSByZXR1cm47XG5cbiAgICAgICAgdmFyIG1pblksIG1heFksIG1pblgsIG1heFgsIHN5LCBzeCwgeDIsIHkyLFxuICAgICAgICAgICAgc2l6ZSA9IHRoaXMuc2l6ZTtcblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgbWluWSA9IHRoaXMubGF0WSh0aGlzLmxhdFJhbmdlWzFdKTtcbiAgICAgICAgICAgIG1heFkgPSB0aGlzLmxhdFkodGhpcy5sYXRSYW5nZVswXSk7XG4gICAgICAgICAgICBzeSA9IG1heFkgLSBtaW5ZIDwgc2l6ZS55ID8gc2l6ZS55IC8gKG1heFkgLSBtaW5ZKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgbWluWCA9IHRoaXMubG5nWCh0aGlzLmxuZ1JhbmdlWzBdKTtcbiAgICAgICAgICAgIG1heFggPSB0aGlzLmxuZ1godGhpcy5sbmdSYW5nZVsxXSk7XG4gICAgICAgICAgICBzeCA9IG1heFggLSBtaW5YIDwgc2l6ZS54ID8gc2l6ZS54IC8gKG1heFggLSBtaW5YKSA6IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob3cgbXVjaCB0aGUgbWFwIHNob3VsZCBzY2FsZSB0byBmaXQgdGhlIHNjcmVlbiBpbnRvIGdpdmVuIGxhdGl0dWRlL2xvbmdpdHVkZSByYW5nZXNcbiAgICAgICAgdmFyIHMgPSBNYXRoLm1heChzeCB8fCAwLCBzeSB8fCAwKTtcblxuICAgICAgICBpZiAocykge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIgPSB0aGlzLnVucHJvamVjdChuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgc3ggPyAobWF4WCArIG1pblgpIC8gMiA6IHRoaXMueCxcbiAgICAgICAgICAgICAgICBzeSA/IChtYXhZICsgbWluWSkgLyAyIDogdGhpcy55KSk7XG4gICAgICAgICAgICB0aGlzLnpvb20gKz0gdGhpcy5zY2FsZVpvb20ocyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sYXRSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHkgPSB0aGlzLnksXG4gICAgICAgICAgICAgICAgaDIgPSBzaXplLnkgLyAyO1xuXG4gICAgICAgICAgICBpZiAoeSAtIGgyIDwgbWluWSkgeTIgPSBtaW5ZICsgaDI7XG4gICAgICAgICAgICBpZiAoeSArIGgyID4gbWF4WSkgeTIgPSBtYXhZIC0gaDI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5sbmdSYW5nZSkge1xuICAgICAgICAgICAgdmFyIHggPSB0aGlzLngsXG4gICAgICAgICAgICAgICAgdzIgPSBzaXplLnggLyAyO1xuXG4gICAgICAgICAgICBpZiAoeCAtIHcyIDwgbWluWCkgeDIgPSBtaW5YICsgdzI7XG4gICAgICAgICAgICBpZiAoeCArIHcyID4gbWF4WCkgeDIgPSBtYXhYIC0gdzI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwYW4gdGhlIG1hcCBpZiB0aGUgc2NyZWVuIGdvZXMgb2ZmIHRoZSByYW5nZVxuICAgICAgICBpZiAoeDIgIT09IHVuZGVmaW5lZCB8fCB5MiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNlbnRlciA9IHRoaXMudW5wcm9qZWN0KG5ldyBQb2ludChcbiAgICAgICAgICAgICAgICB4MiAhPT0gdW5kZWZpbmVkID8geDIgOiB0aGlzLngsXG4gICAgICAgICAgICAgICAgeTIgIT09IHVuZGVmaW5lZCA/IHkyIDogdGhpcy55KSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZ2V0UHJvak1hdHJpeDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtID0gbmV3IEZsb2F0NjRBcnJheSgxNik7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgY2VudGVyIHBvaW50IHRvIHRoZSBjZW50ZXIgdG9wIGluIGFsdGl0dWRlIHVuaXRzIHVzaW5nIGxhdyBvZiBzaW5lcy5cbiAgICAgICAgdmFyIGhhbGZGb3YgPSBNYXRoLmF0YW4oMC41IC8gdGhpcy5hbHRpdHVkZSk7XG4gICAgICAgIHZhciB0b3BIYWxmU3VyZmFjZURpc3RhbmNlID0gTWF0aC5zaW4oaGFsZkZvdikgKiB0aGlzLmFsdGl0dWRlIC8gTWF0aC5zaW4oTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCAtIGhhbGZGb3YpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgeiB2YWx1ZSBvZiB0aGUgZmFydGhlc3QgZnJhZ21lbnQgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAgICAgIHZhciBmYXJaID0gTWF0aC5jb3MoTWF0aC5QSSAvIDIgLSB0aGlzLl9waXRjaCkgKiB0b3BIYWxmU3VyZmFjZURpc3RhbmNlICsgdGhpcy5hbHRpdHVkZTtcblxuICAgICAgICBtYXQ0LnBlcnNwZWN0aXZlKG0sIDIgKiBNYXRoLmF0YW4oKHRoaXMuaGVpZ2h0IC8gMikgLyB0aGlzLmFsdGl0dWRlKSwgdGhpcy53aWR0aCAvIHRoaXMuaGVpZ2h0LCAwLjEsIGZhclopO1xuXG4gICAgICAgIG1hdDQudHJhbnNsYXRlKG0sIG0sIFswLCAwLCAtdGhpcy5hbHRpdHVkZV0pO1xuXG4gICAgICAgIC8vIEFmdGVyIHRoZSByb3RhdGVYLCB6IHZhbHVlcyBhcmUgaW4gcGl4ZWwgdW5pdHMuIENvbnZlcnQgdGhlbSB0b1xuICAgICAgICAvLyBhbHRpdHVkZSB1bml0ZXMuIDEgYWx0aXR1ZGUgdW5pdCA9IHRoZSBzY3JlZW4gaGVpZ2h0LlxuICAgICAgICBtYXQ0LnNjYWxlKG0sIG0sIFsxLCAtMSwgMSAvIHRoaXMuaGVpZ2h0XSk7XG5cbiAgICAgICAgbWF0NC5yb3RhdGVYKG0sIG0sIHRoaXMuX3BpdGNoKTtcbiAgICAgICAgbWF0NC5yb3RhdGVaKG0sIG0sIHRoaXMuYW5nbGUpO1xuICAgICAgICBtYXQ0LnRyYW5zbGF0ZShtLCBtLCBbLXRoaXMueCwgLXRoaXMueSwgMF0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBGb250IGRhdGEgRnJvbSBIZXJzaGV5IFNpbXBsZXggRm9udFxuLy8gaHR0cDovL3BhdWxib3Vya2UubmV0L2RhdGFmb3JtYXRzL2hlcnNoZXkvXG52YXIgc2ltcGxleEZvbnQgPSB7XG4gICAgXCIgXCI6IFsxNiwgW11dLFxuICAgIFwiIVwiOiBbMTAsIFs1LCAyMSwgNSwgNywgLTEsIC0xLCA1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCJcXFwiXCI6IFsxNiwgWzQsIDIxLCA0LCAxNCwgLTEsIC0xLCAxMiwgMjEsIDEyLCAxNF1dLFxuICAgIFwiI1wiOiBbMjEsIFsxMSwgMjUsIDQsIC03LCAtMSwgLTEsIDE3LCAyNSwgMTAsIC03LCAtMSwgLTEsIDQsIDEyLCAxOCwgMTIsIC0xLCAtMSwgMywgNiwgMTcsIDZdXSxcbiAgICBcIiRcIjogWzIwLCBbOCwgMjUsIDgsIC00LCAtMSwgLTEsIDEyLCAyNSwgMTIsIC00LCAtMSwgLTEsIDE3LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxLCA1LCAyMCwgMywgMTgsIDMsIDE2LCA0LCAxNCwgNSwgMTMsIDcsIDEyLCAxMywgMTAsIDE1LCA5LCAxNiwgOCwgMTcsIDYsIDE3LCAzLCAxNSwgMSwgMTIsIDAsIDgsIDAsIDUsIDEsIDMsIDNdXSxcbiAgICBcIiVcIjogWzI0LCBbMjEsIDIxLCAzLCAwLCAtMSwgLTEsIDgsIDIxLCAxMCwgMTksIDEwLCAxNywgOSwgMTUsIDcsIDE0LCA1LCAxNCwgMywgMTYsIDMsIDE4LCA0LCAyMCwgNiwgMjEsIDgsIDIxLCAxMCwgMjAsIDEzLCAxOSwgMTYsIDE5LCAxOSwgMjAsIDIxLCAyMSwgLTEsIC0xLCAxNywgNywgMTUsIDYsIDE0LCA0LCAxNCwgMiwgMTYsIDAsIDE4LCAwLCAyMCwgMSwgMjEsIDMsIDIxLCA1LCAxOSwgNywgMTcsIDddXSxcbiAgICBcIiZcIjogWzI2LCBbMjMsIDEyLCAyMywgMTMsIDIyLCAxNCwgMjEsIDE0LCAyMCwgMTMsIDE5LCAxMSwgMTcsIDYsIDE1LCAzLCAxMywgMSwgMTEsIDAsIDcsIDAsIDUsIDEsIDQsIDIsIDMsIDQsIDMsIDYsIDQsIDgsIDUsIDksIDEyLCAxMywgMTMsIDE0LCAxNCwgMTYsIDE0LCAxOCwgMTMsIDIwLCAxMSwgMjEsIDksIDIwLCA4LCAxOCwgOCwgMTYsIDksIDEzLCAxMSwgMTAsIDE2LCAzLCAxOCwgMSwgMjAsIDAsIDIyLCAwLCAyMywgMSwgMjMsIDJdXSxcbiAgICBcIidcIjogWzEwLCBbNSwgMTksIDQsIDIwLCA1LCAyMSwgNiwgMjAsIDYsIDE4LCA1LCAxNiwgNCwgMTVdXSxcbiAgICBcIihcIjogWzE0LCBbMTEsIDI1LCA5LCAyMywgNywgMjAsIDUsIDE2LCA0LCAxMSwgNCwgNywgNSwgMiwgNywgLTIsIDksIC01LCAxMSwgLTddXSxcbiAgICBcIilcIjogWzE0LCBbMywgMjUsIDUsIDIzLCA3LCAyMCwgOSwgMTYsIDEwLCAxMSwgMTAsIDcsIDksIDIsIDcsIC0yLCA1LCAtNSwgMywgLTddXSxcbiAgICBcIipcIjogWzE2LCBbOCwgMjEsIDgsIDksIC0xLCAtMSwgMywgMTgsIDEzLCAxMiwgLTEsIC0xLCAxMywgMTgsIDMsIDEyXV0sXG4gICAgXCIrXCI6IFsyNiwgWzEzLCAxOCwgMTMsIDAsIC0xLCAtMSwgNCwgOSwgMjIsIDldXSxcbiAgICBcIixcIjogWzEwLCBbNiwgMSwgNSwgMCwgNCwgMSwgNSwgMiwgNiwgMSwgNiwgLTEsIDUsIC0zLCA0LCAtNF1dLFxuICAgIFwiLVwiOiBbMjYsIFs0LCA5LCAyMiwgOV1dLFxuICAgIFwiLlwiOiBbMTAsIFs1LCAyLCA0LCAxLCA1LCAwLCA2LCAxLCA1LCAyXV0sXG4gICAgXCIvXCI6IFsyMiwgWzIwLCAyNSwgMiwgLTddXSxcbiAgICBcIjBcIjogWzIwLCBbOSwgMjEsIDYsIDIwLCA0LCAxNywgMywgMTIsIDMsIDksIDQsIDQsIDYsIDEsIDksIDAsIDExLCAwLCAxNCwgMSwgMTYsIDQsIDE3LCA5LCAxNywgMTIsIDE2LCAxNywgMTQsIDIwLCAxMSwgMjEsIDksIDIxXV0sXG4gICAgXCIxXCI6IFsyMCwgWzYsIDE3LCA4LCAxOCwgMTEsIDIxLCAxMSwgMF1dLFxuICAgIFwiMlwiOiBbMjAsIFs0LCAxNiwgNCwgMTcsIDUsIDE5LCA2LCAyMCwgOCwgMjEsIDEyLCAyMSwgMTQsIDIwLCAxNSwgMTksIDE2LCAxNywgMTYsIDE1LCAxNSwgMTMsIDEzLCAxMCwgMywgMCwgMTcsIDBdXSxcbiAgICBcIjNcIjogWzIwLCBbNSwgMjEsIDE2LCAyMSwgMTAsIDEzLCAxMywgMTMsIDE1LCAxMiwgMTYsIDExLCAxNywgOCwgMTcsIDYsIDE2LCAzLCAxNCwgMSwgMTEsIDAsIDgsIDAsIDUsIDEsIDQsIDIsIDMsIDRdXSxcbiAgICBcIjRcIjogWzIwLCBbMTMsIDIxLCAzLCA3LCAxOCwgNywgLTEsIC0xLCAxMywgMjEsIDEzLCAwXV0sXG4gICAgXCI1XCI6IFsyMCwgWzE1LCAyMSwgNSwgMjEsIDQsIDEyLCA1LCAxMywgOCwgMTQsIDExLCAxNCwgMTQsIDEzLCAxNiwgMTEsIDE3LCA4LCAxNywgNiwgMTYsIDMsIDE0LCAxLCAxMSwgMCwgOCwgMCwgNSwgMSwgNCwgMiwgMywgNF1dLFxuICAgIFwiNlwiOiBbMjAsIFsxNiwgMTgsIDE1LCAyMCwgMTIsIDIxLCAxMCwgMjEsIDcsIDIwLCA1LCAxNywgNCwgMTIsIDQsIDcsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMSwgMCwgMTQsIDEsIDE2LCAzLCAxNywgNiwgMTcsIDcsIDE2LCAxMCwgMTQsIDEyLCAxMSwgMTMsIDEwLCAxMywgNywgMTIsIDUsIDEwLCA0LCA3XV0sXG4gICAgXCI3XCI6IFsyMCwgWzE3LCAyMSwgNywgMCwgLTEsIC0xLCAzLCAyMSwgMTcsIDIxXV0sXG4gICAgXCI4XCI6IFsyMCwgWzgsIDIxLCA1LCAyMCwgNCwgMTgsIDQsIDE2LCA1LCAxNCwgNywgMTMsIDExLCAxMiwgMTQsIDExLCAxNiwgOSwgMTcsIDcsIDE3LCA0LCAxNiwgMiwgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCA0LCAyLCAzLCA0LCAzLCA3LCA0LCA5LCA2LCAxMSwgOSwgMTIsIDEzLCAxMywgMTUsIDE0LCAxNiwgMTYsIDE2LCAxOCwgMTUsIDIwLCAxMiwgMjEsIDgsIDIxXV0sXG4gICAgXCI5XCI6IFsyMCwgWzE2LCAxNCwgMTUsIDExLCAxMywgOSwgMTAsIDgsIDksIDgsIDYsIDksIDQsIDExLCAzLCAxNCwgMywgMTUsIDQsIDE4LCA2LCAyMCwgOSwgMjEsIDEwLCAyMSwgMTMsIDIwLCAxNSwgMTgsIDE2LCAxNCwgMTYsIDksIDE1LCA0LCAxMywgMSwgMTAsIDAsIDgsIDAsIDUsIDEsIDQsIDNdXSxcbiAgICBcIjpcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDUsIDIsIDQsIDEsIDUsIDAsIDYsIDEsIDUsIDJdXSxcbiAgICBcIjtcIjogWzEwLCBbNSwgMTQsIDQsIDEzLCA1LCAxMiwgNiwgMTMsIDUsIDE0LCAtMSwgLTEsIDYsIDEsIDUsIDAsIDQsIDEsIDUsIDIsIDYsIDEsIDYsIC0xLCA1LCAtMywgNCwgLTRdXSxcbiAgICBcIjxcIjogWzI0LCBbMjAsIDE4LCA0LCA5LCAyMCwgMF1dLFxuICAgIFwiPVwiOiBbMjYsIFs0LCAxMiwgMjIsIDEyLCAtMSwgLTEsIDQsIDYsIDIyLCA2XV0sXG4gICAgXCI+XCI6IFsyNCwgWzQsIDE4LCAyMCwgOSwgNCwgMF1dLFxuICAgIFwiP1wiOiBbMTgsIFszLCAxNiwgMywgMTcsIDQsIDE5LCA1LCAyMCwgNywgMjEsIDExLCAyMSwgMTMsIDIwLCAxNCwgMTksIDE1LCAxNywgMTUsIDE1LCAxNCwgMTMsIDEzLCAxMiwgOSwgMTAsIDksIDcsIC0xLCAtMSwgOSwgMiwgOCwgMSwgOSwgMCwgMTAsIDEsIDksIDJdXSxcbiAgICBcIkBcIjogWzI3LCBbMTgsIDEzLCAxNywgMTUsIDE1LCAxNiwgMTIsIDE2LCAxMCwgMTUsIDksIDE0LCA4LCAxMSwgOCwgOCwgOSwgNiwgMTEsIDUsIDE0LCA1LCAxNiwgNiwgMTcsIDgsIC0xLCAtMSwgMTIsIDE2LCAxMCwgMTQsIDksIDExLCA5LCA4LCAxMCwgNiwgMTEsIDUsIC0xLCAtMSwgMTgsIDE2LCAxNywgOCwgMTcsIDYsIDE5LCA1LCAyMSwgNSwgMjMsIDcsIDI0LCAxMCwgMjQsIDEyLCAyMywgMTUsIDIyLCAxNywgMjAsIDE5LCAxOCwgMjAsIDE1LCAyMSwgMTIsIDIxLCA5LCAyMCwgNywgMTksIDUsIDE3LCA0LCAxNSwgMywgMTIsIDMsIDksIDQsIDYsIDUsIDQsIDcsIDIsIDksIDEsIDEyLCAwLCAxNSwgMCwgMTgsIDEsIDIwLCAyLCAyMSwgMywgLTEsIC0xLCAxOSwgMTYsIDE4LCA4LCAxOCwgNiwgMTksIDVdXSxcbiAgICBcIkFcIjogWzE4LCBbOSwgMjEsIDEsIDAsIC0xLCAtMSwgOSwgMjEsIDE3LCAwLCAtMSwgLTEsIDQsIDcsIDE0LCA3XV0sXG4gICAgXCJCXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgLTEsIC0xLCA0LCAxMSwgMTMsIDExLCAxNiwgMTAsIDE3LCA5LCAxOCwgNywgMTgsIDQsIDE3LCAyLCAxNiwgMSwgMTMsIDAsIDQsIDBdXSxcbiAgICBcIkNcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1XV0sXG4gICAgXCJEXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMSwgMjEsIDE0LCAyMCwgMTYsIDE4LCAxNywgMTYsIDE4LCAxMywgMTgsIDgsIDE3LCA1LCAxNiwgMywgMTQsIDEsIDExLCAwLCA0LCAwXV0sXG4gICAgXCJFXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxNywgMjEsIC0xLCAtMSwgNCwgMTEsIDEyLCAxMSwgLTEsIC0xLCA0LCAwLCAxNywgMF1dLFxuICAgIFwiRlwiOiBbMTgsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTcsIDIxLCAtMSwgLTEsIDQsIDExLCAxMiwgMTFdXSxcbiAgICBcIkdcIjogWzIxLCBbMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOCwgOCwgLTEsIC0xLCAxMywgOCwgMTgsIDhdXSxcbiAgICBcIkhcIjogWzIyLCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMCwgLTEsIC0xLCA0LCAxMSwgMTgsIDExXV0sXG4gICAgXCJJXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIkpcIjogWzE2LCBbMTIsIDIxLCAxMiwgNSwgMTEsIDIsIDEwLCAxLCA4LCAwLCA2LCAwLCA0LCAxLCAzLCAyLCAyLCA1LCAyLCA3XV0sXG4gICAgXCJLXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDE4LCAyMSwgNCwgNywgLTEsIC0xLCA5LCAxMiwgMTgsIDBdXSxcbiAgICBcIkxcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMCwgMTYsIDBdXSxcbiAgICBcIk1cIjogWzI0LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgNCwgMjEsIDEyLCAwLCAtMSwgLTEsIDIwLCAyMSwgMTIsIDAsIC0xLCAtMSwgMjAsIDIxLCAyMCwgMF1dLFxuICAgIFwiTlwiOiBbMjIsIFs0LCAyMSwgNCwgMCwgLTEsIC0xLCA0LCAyMSwgMTgsIDAsIC0xLCAtMSwgMTgsIDIxLCAxOCwgMF1dLFxuICAgIFwiT1wiOiBbMjIsIFs5LCAyMSwgNywgMjAsIDUsIDE4LCA0LCAxNiwgMywgMTMsIDMsIDgsIDQsIDUsIDUsIDMsIDcsIDEsIDksIDAsIDEzLCAwLCAxNSwgMSwgMTcsIDMsIDE4LCA1LCAxOSwgOCwgMTksIDEzLCAxOCwgMTYsIDE3LCAxOCwgMTUsIDIwLCAxMywgMjEsIDksIDIxXV0sXG4gICAgXCJQXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNCwgMTcsIDEyLCAxNiwgMTEsIDEzLCAxMCwgNCwgMTBdXSxcbiAgICBcIlFcIjogWzIyLCBbOSwgMjEsIDcsIDIwLCA1LCAxOCwgNCwgMTYsIDMsIDEzLCAzLCA4LCA0LCA1LCA1LCAzLCA3LCAxLCA5LCAwLCAxMywgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNSwgMTksIDgsIDE5LCAxMywgMTgsIDE2LCAxNywgMTgsIDE1LCAyMCwgMTMsIDIxLCA5LCAyMSwgLTEsIC0xLCAxMiwgNCwgMTgsIC0yXV0sXG4gICAgXCJSXCI6IFsyMSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDIxLCAxMywgMjEsIDE2LCAyMCwgMTcsIDE5LCAxOCwgMTcsIDE4LCAxNSwgMTcsIDEzLCAxNiwgMTIsIDEzLCAxMSwgNCwgMTEsIC0xLCAtMSwgMTEsIDExLCAxOCwgMF1dLFxuICAgIFwiU1wiOiBbMjAsIFsxNywgMTgsIDE1LCAyMCwgMTIsIDIxLCA4LCAyMSwgNSwgMjAsIDMsIDE4LCAzLCAxNiwgNCwgMTQsIDUsIDEzLCA3LCAxMiwgMTMsIDEwLCAxNSwgOSwgMTYsIDgsIDE3LCA2LCAxNywgMywgMTUsIDEsIDEyLCAwLCA4LCAwLCA1LCAxLCAzLCAzXV0sXG4gICAgXCJUXCI6IFsxNiwgWzgsIDIxLCA4LCAwLCAtMSwgLTEsIDEsIDIxLCAxNSwgMjFdXSxcbiAgICBcIlVcIjogWzIyLCBbNCwgMjEsIDQsIDYsIDUsIDMsIDcsIDEsIDEwLCAwLCAxMiwgMCwgMTUsIDEsIDE3LCAzLCAxOCwgNiwgMTgsIDIxXV0sXG4gICAgXCJWXCI6IFsxOCwgWzEsIDIxLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMF1dLFxuICAgIFwiV1wiOiBbMjQsIFsyLCAyMSwgNywgMCwgLTEsIC0xLCAxMiwgMjEsIDcsIDAsIC0xLCAtMSwgMTIsIDIxLCAxNywgMCwgLTEsIC0xLCAyMiwgMjEsIDE3LCAwXV0sXG4gICAgXCJYXCI6IFsyMCwgWzMsIDIxLCAxNywgMCwgLTEsIC0xLCAxNywgMjEsIDMsIDBdXSxcbiAgICBcIllcIjogWzE4LCBbMSwgMjEsIDksIDExLCA5LCAwLCAtMSwgLTEsIDE3LCAyMSwgOSwgMTFdXSxcbiAgICBcIlpcIjogWzIwLCBbMTcsIDIxLCAzLCAwLCAtMSwgLTEsIDMsIDIxLCAxNywgMjEsIC0xLCAtMSwgMywgMCwgMTcsIDBdXSxcbiAgICBcIltcIjogWzE0LCBbNCwgMjUsIDQsIC03LCAtMSwgLTEsIDUsIDI1LCA1LCAtNywgLTEsIC0xLCA0LCAyNSwgMTEsIDI1LCAtMSwgLTEsIDQsIC03LCAxMSwgLTddXSxcbiAgICBcIlxcXFxcIjogWzE0LCBbMCwgMjEsIDE0LCAtM11dLFxuICAgIFwiXVwiOiBbMTQsIFs5LCAyNSwgOSwgLTcsIC0xLCAtMSwgMTAsIDI1LCAxMCwgLTcsIC0xLCAtMSwgMywgMjUsIDEwLCAyNSwgLTEsIC0xLCAzLCAtNywgMTAsIC03XV0sXG4gICAgXCJeXCI6IFsxNiwgWzYsIDE1LCA4LCAxOCwgMTAsIDE1LCAtMSwgLTEsIDMsIDEyLCA4LCAxNywgMTMsIDEyLCAtMSwgLTEsIDgsIDE3LCA4LCAwXV0sXG4gICAgXCJfXCI6IFsxNiwgWzAsIC0yLCAxNiwgLTJdXSxcbiAgICBcImBcIjogWzEwLCBbNiwgMjEsIDUsIDIwLCA0LCAxOCwgNCwgMTYsIDUsIDE1LCA2LCAxNiwgNSwgMTddXSxcbiAgICBcImFcIjogWzE5LCBbMTUsIDE0LCAxNSwgMCwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJiXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDExLCA2LCAxMywgOCwgMTQsIDExLCAxNCwgMTMsIDEzLCAxNSwgMTEsIDE2LCA4LCAxNiwgNiwgMTUsIDMsIDEzLCAxLCAxMSwgMCwgOCwgMCwgNiwgMSwgNCwgM11dLFxuICAgIFwiY1wiOiBbMTgsIFsxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJkXCI6IFsxOSwgWzE1LCAyMSwgMTUsIDAsIC0xLCAtMSwgMTUsIDExLCAxMywgMTMsIDExLCAxNCwgOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgM11dLFxuICAgIFwiZVwiOiBbMTgsIFszLCA4LCAxNSwgOCwgMTUsIDEwLCAxNCwgMTIsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJmXCI6IFsxMiwgWzEwLCAyMSwgOCwgMjEsIDYsIDIwLCA1LCAxNywgNSwgMCwgLTEsIC0xLCAyLCAxNCwgOSwgMTRdXSxcbiAgICBcImdcIjogWzE5LCBbMTUsIDE0LCAxNSwgLTIsIDE0LCAtNSwgMTMsIC02LCAxMSwgLTcsIDgsIC03LCA2LCAtNiwgLTEsIC0xLCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNCwgNiwgMTMsIDQsIDExLCAzLCA4LCAzLCA2LCA0LCAzLCA2LCAxLCA4LCAwLCAxMSwgMCwgMTMsIDEsIDE1LCAzXV0sXG4gICAgXCJoXCI6IFsxOSwgWzQsIDIxLCA0LCAwLCAtMSwgLTEsIDQsIDEwLCA3LCAxMywgOSwgMTQsIDEyLCAxNCwgMTQsIDEzLCAxNSwgMTAsIDE1LCAwXV0sXG4gICAgXCJpXCI6IFs4LCBbMywgMjEsIDQsIDIwLCA1LCAyMSwgNCwgMjIsIDMsIDIxLCAtMSwgLTEsIDQsIDE0LCA0LCAwXV0sXG4gICAgXCJqXCI6IFsxMCwgWzUsIDIxLCA2LCAyMCwgNywgMjEsIDYsIDIyLCA1LCAyMSwgLTEsIC0xLCA2LCAxNCwgNiwgLTMsIDUsIC02LCAzLCAtNywgMSwgLTddXSxcbiAgICBcImtcIjogWzE3LCBbNCwgMjEsIDQsIDAsIC0xLCAtMSwgMTQsIDE0LCA0LCA0LCAtMSwgLTEsIDgsIDgsIDE1LCAwXV0sXG4gICAgXCJsXCI6IFs4LCBbNCwgMjEsIDQsIDBdXSxcbiAgICBcIm1cIjogWzMwLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDAsIC0xLCAtMSwgMTUsIDEwLCAxOCwgMTMsIDIwLCAxNCwgMjMsIDE0LCAyNSwgMTMsIDI2LCAxMCwgMjYsIDBdXSxcbiAgICBcIm5cIjogWzE5LCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgMTAsIDcsIDEzLCA5LCAxNCwgMTIsIDE0LCAxNCwgMTMsIDE1LCAxMCwgMTUsIDBdXSxcbiAgICBcIm9cIjogWzE5LCBbOCwgMTQsIDYsIDEzLCA0LCAxMSwgMywgOCwgMywgNiwgNCwgMywgNiwgMSwgOCwgMCwgMTEsIDAsIDEzLCAxLCAxNSwgMywgMTYsIDYsIDE2LCA4LCAxNSwgMTEsIDEzLCAxMywgMTEsIDE0LCA4LCAxNF1dLFxuICAgIFwicFwiOiBbMTksIFs0LCAxNCwgNCwgLTcsIC0xLCAtMSwgNCwgMTEsIDYsIDEzLCA4LCAxNCwgMTEsIDE0LCAxMywgMTMsIDE1LCAxMSwgMTYsIDgsIDE2LCA2LCAxNSwgMywgMTMsIDEsIDExLCAwLCA4LCAwLCA2LCAxLCA0LCAzXV0sXG4gICAgXCJxXCI6IFsxOSwgWzE1LCAxNCwgMTUsIC03LCAtMSwgLTEsIDE1LCAxMSwgMTMsIDEzLCAxMSwgMTQsIDgsIDE0LCA2LCAxMywgNCwgMTEsIDMsIDgsIDMsIDYsIDQsIDMsIDYsIDEsIDgsIDAsIDExLCAwLCAxMywgMSwgMTUsIDNdXSxcbiAgICBcInJcIjogWzEzLCBbNCwgMTQsIDQsIDAsIC0xLCAtMSwgNCwgOCwgNSwgMTEsIDcsIDEzLCA5LCAxNCwgMTIsIDE0XV0sXG4gICAgXCJzXCI6IFsxNywgWzE0LCAxMSwgMTMsIDEzLCAxMCwgMTQsIDcsIDE0LCA0LCAxMywgMywgMTEsIDQsIDksIDYsIDgsIDExLCA3LCAxMywgNiwgMTQsIDQsIDE0LCAzLCAxMywgMSwgMTAsIDAsIDcsIDAsIDQsIDEsIDMsIDNdXSxcbiAgICBcInRcIjogWzEyLCBbNSwgMjEsIDUsIDQsIDYsIDEsIDgsIDAsIDEwLCAwLCAtMSwgLTEsIDIsIDE0LCA5LCAxNF1dLFxuICAgIFwidVwiOiBbMTksIFs0LCAxNCwgNCwgNCwgNSwgMSwgNywgMCwgMTAsIDAsIDEyLCAxLCAxNSwgNCwgLTEsIC0xLCAxNSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ2XCI6IFsxNiwgWzIsIDE0LCA4LCAwLCAtMSwgLTEsIDE0LCAxNCwgOCwgMF1dLFxuICAgIFwid1wiOiBbMjIsIFszLCAxNCwgNywgMCwgLTEsIC0xLCAxMSwgMTQsIDcsIDAsIC0xLCAtMSwgMTEsIDE0LCAxNSwgMCwgLTEsIC0xLCAxOSwgMTQsIDE1LCAwXV0sXG4gICAgXCJ4XCI6IFsxNywgWzMsIDE0LCAxNCwgMCwgLTEsIC0xLCAxNCwgMTQsIDMsIDBdXSxcbiAgICBcInlcIjogWzE2LCBbMiwgMTQsIDgsIDAsIC0xLCAtMSwgMTQsIDE0LCA4LCAwLCA2LCAtNCwgNCwgLTYsIDIsIC03LCAxLCAtN11dLFxuICAgIFwielwiOiBbMTcsIFsxNCwgMTQsIDMsIDAsIC0xLCAtMSwgMywgMTQsIDE0LCAxNCwgLTEsIC0xLCAzLCAwLCAxNCwgMF1dLFxuICAgIFwie1wiOiBbMTQsIFs5LCAyNSwgNywgMjQsIDYsIDIzLCA1LCAyMSwgNSwgMTksIDYsIDE3LCA3LCAxNiwgOCwgMTQsIDgsIDEyLCA2LCAxMCwgLTEsIC0xLCA3LCAyNCwgNiwgMjIsIDYsIDIwLCA3LCAxOCwgOCwgMTcsIDksIDE1LCA5LCAxMywgOCwgMTEsIDQsIDksIDgsIDcsIDksIDUsIDksIDMsIDgsIDEsIDcsIDAsIDYsIC0yLCA2LCAtNCwgNywgLTYsIC0xLCAtMSwgNiwgOCwgOCwgNiwgOCwgNCwgNywgMiwgNiwgMSwgNSwgLTEsIDUsIC0zLCA2LCAtNSwgNywgLTYsIDksIC03XV0sXG4gICAgXCJ8XCI6IFs4LCBbNCwgMjUsIDQsIC03XV0sXG4gICAgXCJ9XCI6IFsxNCwgWzUsIDI1LCA3LCAyNCwgOCwgMjMsIDksIDIxLCA5LCAxOSwgOCwgMTcsIDcsIDE2LCA2LCAxNCwgNiwgMTIsIDgsIDEwLCAtMSwgLTEsIDcsIDI0LCA4LCAyMiwgOCwgMjAsIDcsIDE4LCA2LCAxNywgNSwgMTUsIDUsIDEzLCA2LCAxMSwgMTAsIDksIDYsIDcsIDUsIDUsIDUsIDMsIDYsIDEsIDcsIDAsIDgsIC0yLCA4LCAtNCwgNywgLTYsIC0xLCAtMSwgOCwgOCwgNiwgNiwgNiwgNCwgNywgMiwgOCwgMSwgOSwgLTEsIDksIC0zLCA4LCAtNSwgNywgLTYsIDUsIC03XV0sXG4gICAgXCJ+XCI6IFsyNCwgWzMsIDYsIDMsIDgsIDQsIDExLCA2LCAxMiwgOCwgMTIsIDEwLCAxMSwgMTQsIDgsIDE2LCA3LCAxOCwgNywgMjAsIDgsIDIxLCAxMCwgLTEsIC0xLCAzLCA4LCA0LCAxMCwgNiwgMTEsIDgsIDExLCAxMCwgMTAsIDE0LCA3LCAxNiwgNiwgMTgsIDYsIDIwLCA3LCAyMSwgMTAsIDIxLCAxMl1dXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRleHRWZXJ0aWNlcyh0ZXh0LCBsZWZ0LCBiYXNlbGluZSwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDE7XG5cbiAgICB2YXIgc3Ryb2tlcyA9IFtdLFxuICAgICAgICBpLCBsZW4sIGosIGxlbjIsIGdseXBoLCB4LCB5LCBwcmV2O1xuXG4gICAgZm9yIChpID0gMCwgbGVuID0gdGV4dC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBnbHlwaCA9IHNpbXBsZXhGb250W3RleHRbaV1dO1xuICAgICAgICBpZiAoIWdseXBoKSBjb250aW51ZTtcbiAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgZm9yIChqID0gMCwgbGVuMiA9IGdseXBoWzFdLmxlbmd0aDsgaiA8IGxlbjI7IGogKz0gMikge1xuICAgICAgICAgICAgaWYgKGdseXBoWzFdW2pdID09PSAtMSAmJiBnbHlwaFsxXVtqICsgMV0gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcHJldiA9IG51bGw7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgeCA9IGxlZnQgKyBnbHlwaFsxXVtqXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIHkgPSBiYXNlbGluZSAtIGdseXBoWzFdW2ogKyAxXSAqIHNjYWxlO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZXMucHVzaChwcmV2LngsIHByZXYueSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXYgPSB7eDogeCwgeTogeX07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGVmdCArPSBnbHlwaFswXSAqIHNjYWxlO1xuICAgIH1cblxuICAgIHJldHVybiBzdHJva2VzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBtYXBib3hnbCBpcyBhIEEgV2ViR0wgSmF2YVNjcmlwdCBpbnRlcmFjdGl2ZSBtYXBzIGxpYnJhcnkgdGhhdCBjYW4gcmVuZGVyXG4gKiBbTWFwYm94IHZlY3RvciB0aWxlc10oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9ibG9nL3ZlY3Rvci10aWxlcy8pLlxuICpcbiAqIEBtb2R1bGUgbWFwYm94Z2xcbiAqIEBzdW1tYXJ5IFdlYkdMIEphdmFTY3JpcHQgbWFwIGxpYnJhcnlcbiAqL1xuXG4vLyBqc2hpbnQgLVcwNzlcbnZhciBtYXBib3hnbCA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbm1hcGJveGdsLk1hcCA9IHJlcXVpcmUoJy4vdWkvbWFwJyk7XG5tYXBib3hnbC5OYXZpZ2F0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL25hdmlnYXRpb24nKTtcbm1hcGJveGdsLkF0dHJpYnV0aW9uID0gcmVxdWlyZSgnLi91aS9jb250cm9sL2F0dHJpYnV0aW9uJyk7XG5tYXBib3hnbC5Qb3B1cCA9IHJlcXVpcmUoJy4vdWkvcG9wdXAnKTtcblxubWFwYm94Z2wuR2VvSlNPTlNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL2dlb2pzb25fc291cmNlJyk7XG5tYXBib3hnbC5WaWRlb1NvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlL3ZpZGVvX3NvdXJjZScpO1xuXG5tYXBib3hnbC5TdHlsZSA9IHJlcXVpcmUoJy4vc3R5bGUvc3R5bGUnKTtcblxubWFwYm94Z2wuTGF0TG5nID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZycpO1xubWFwYm94Z2wuTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbm1hcGJveGdsLlBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubWFwYm94Z2wuRXZlbnRlZCA9IHJlcXVpcmUoJy4vdXRpbC9ldmVudGVkJyk7XG5tYXBib3hnbC51dGlsID0gcmVxdWlyZSgnLi91dGlsL3V0aWwnKTtcblxubWFwYm94Z2wuc3VwcG9ydGVkID0gcmVxdWlyZSgnLi91dGlsL2Jyb3dzZXInKS5zdXBwb3J0ZWQ7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi91dGlsL2FqYXgnKTtcbm1hcGJveGdsLnV0aWwuZ2V0SlNPTiA9IGFqYXguZ2V0SlNPTjtcbm1hcGJveGdsLnV0aWwuZ2V0QXJyYXlCdWZmZXIgPSBhamF4LmdldEFycmF5QnVmZmVyO1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi91dGlsL2NvbmZpZycpO1xubWFwYm94Z2wuY29uZmlnID0gY29uZmlnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWFwYm94Z2wsICdhY2Nlc3NUb2tlbicsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnLkFDQ0VTU19UT0tFTjsgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHRva2VuKSB7IGNvbmZpZy5BQ0NFU1NfVE9LRU4gPSB0b2tlbjsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBtYXQzID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0MztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3QmFja2dyb3VuZDtcblxuZnVuY3Rpb24gZHJhd0JhY2tncm91bmQocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtY29sb3InXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnYmFja2dyb3VuZC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2JhY2tncm91bmQtb3BhY2l0eSddO1xuICAgIHZhciBzaGFkZXI7XG5cbiAgICB2YXIgaW1hZ2VQb3NBID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpIDogbnVsbDtcbiAgICB2YXIgaW1hZ2VQb3NCID0gaW1hZ2UgPyBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLnRvLCB0cnVlKSA6IG51bGw7XG5cbiAgICBpZiAoaW1hZ2VQb3NBICYmIGltYWdlUG9zQikge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZSwgMCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9hLCBpbWFnZVBvc0EudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYSwgaW1hZ2VQb3NBLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2IsIGltYWdlUG9zQi50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9iLCBpbWFnZVBvc0IuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eSwgb3BhY2l0eSk7XG5cbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgICAgICB2YXIgc2l6ZUEgPSBpbWFnZVBvc0Euc2l6ZTtcbiAgICAgICAgdmFyIHNpemVCID0gaW1hZ2VQb3NCLnNpemU7XG4gICAgICAgIHZhciBjZW50ZXIgPSB0cmFuc2Zvcm0ubG9jYXRpb25Db29yZGluYXRlKHRyYW5zZm9ybS5jZW50ZXIpO1xuICAgICAgICB2YXIgc2NhbGUgPSAxIC8gTWF0aC5wb3coMiwgdHJhbnNmb3JtLnpvb21GcmFjdGlvbik7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21peCwgaW1hZ2UudCk7XG5cbiAgICAgICAgdmFyIG1hdHJpeEEgPSBtYXQzLmNyZWF0ZSgpO1xuICAgICAgICBtYXQzLnNjYWxlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIDEgLyAoc2l6ZUFbMF0gKiBpbWFnZS5mcm9tU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQVsxXSAqIGltYWdlLmZyb21TY2FsZSlcbiAgICAgICAgXSk7XG4gICAgICAgIG1hdDMudHJhbnNsYXRlKG1hdHJpeEEsIG1hdHJpeEEsIFtcbiAgICAgICAgICAgIChjZW50ZXIuY29sdW1uICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQVswXSAqIGltYWdlLmZyb21TY2FsZSksXG4gICAgICAgICAgICAoY2VudGVyLnJvdyAgICAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUFbMV0gKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhBLCBtYXRyaXhBLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICB2YXIgbWF0cml4QiA9IG1hdDMuY3JlYXRlKCk7XG4gICAgICAgIG1hdDMuc2NhbGUobWF0cml4QiwgbWF0cml4QiwgW1xuICAgICAgICAgICAgMSAvIChzaXplQlswXSAqIGltYWdlLnRvU2NhbGUpLFxuICAgICAgICAgICAgMSAvIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnRyYW5zbGF0ZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAoY2VudGVyLmNvbHVtbiAqIHRyYW5zZm9ybS50aWxlU2l6ZSkgJSAoc2l6ZUJbMF0gKiBpbWFnZS50b1NjYWxlKSxcbiAgICAgICAgICAgIChjZW50ZXIucm93ICAgICogdHJhbnNmb3JtLnRpbGVTaXplKSAlIChzaXplQlsxXSAqIGltYWdlLnRvU2NhbGUpXG4gICAgICAgIF0pO1xuICAgICAgICBtYXQzLnJvdGF0ZShtYXRyaXhCLCBtYXRyaXhCLCAtdHJhbnNmb3JtLmFuZ2xlKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICBzY2FsZSAqIHRyYW5zZm9ybS53aWR0aCAgLyAyLFxuICAgICAgICAgICAtc2NhbGUgKiB0cmFuc2Zvcm0uaGVpZ2h0IC8gMlxuICAgICAgICBdKTtcblxuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYSwgZmFsc2UsIG1hdHJpeEEpO1xuICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KHNoYWRlci51X3BhdHRlcm5tYXRyaXhfYiwgZmFsc2UsIG1hdHJpeEIpO1xuXG4gICAgICAgIHBhaW50ZXIuc3ByaXRlQXRsYXMuYmluZChnbCwgdHJ1ZSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEcmF3IGZpbGxpbmcgcmVjdGFuZ2xlLlxuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmZpbGxTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHBvc01hdHJpeCk7XG4gICAgICAgIGdsLnVuaWZvcm00ZnYoc2hhZGVyLnVfY29sb3IsIGNvbG9yKTtcbiAgICB9XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihzaGFkZXIuYV9wb3MsIHBhaW50ZXIuYmFja2dyb3VuZEJ1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCBwYWludGVyLmJhY2tncm91bmRCdWZmZXIuaXRlbUNvdW50KTtcbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcblxuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLnN0ZW5jaWxGdW5jKGdsLkVRVUFMLCAweDgwLCAweDgwKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3UGxhY2VtZW50RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdQbGFjZW1lbnREZWJ1ZyhwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlKSB7XG5cbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdLmNvbGxpc2lvbkJveDtcbiAgICBpZiAoIWVsZW1lbnRHcm91cHMpIHJldHVybjtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG4gICAgdmFyIGJ1ZmZlciA9IHRpbGUuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgdmFyIHNoYWRlciA9IHBhaW50ZXIuY29sbGlzaW9uQm94U2hhZGVyO1xuXG4gICAgZ2wuZW5hYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgIGJ1ZmZlci5iaW5kKGdsLCBzaGFkZXIpO1xuICAgIGdsLmxpbmVXaWR0aCgzKTtcblxuICAgIHZhciBzdHJpZGUgPSAxMjtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZXh0cnVkZSwgMiwgZ2wuU0hPUlQsIGZhbHNlLCBzdHJpZGUsIDQpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfZGF0YSwgMiwgZ2wuVU5TSUdORURfQllURSwgZmFsc2UsIHN0cmlkZSwgOCk7XG5cbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2NhbGUsIE1hdGgucG93KDIsIHBhaW50ZXIudHJhbnNmb3JtLnpvb20gLSB0aWxlLmNvb3JkLnopKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfem9vbSwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWF4em9vbSwgKHRpbGUuY29vcmQueiArIDEpICogMTApO1xuXG4gICAgdmFyIGJlZ2luID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4U3RhcnRJbmRleDtcbiAgICB2YXIgbGVuID0gZWxlbWVudEdyb3Vwcy5ncm91cHNbMF0udmVydGV4TGVuZ3RoO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIGJlZ2luLCBsZW4pO1xuXG4gICAgZ2wuZGlzYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdGV4dFZlcnRpY2VzID0gcmVxdWlyZSgnLi4vbGliL2RlYnVndGV4dCcpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3RGVidWc7XG5cbmZ1bmN0aW9uIGRyYXdEZWJ1ZyhwYWludGVyLCB0aWxlKSB7XG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcblxuICAgIC8vIEJsZW5kIHRvIHRoZSBmcm9udCwgbm90IHRoZSBiYWNrLlxuICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZGVidWdTaGFkZXIsIHRpbGUucG9zTWF0cml4KTtcblxuICAgIC8vIGRyYXcgYm91bmRpbmcgcmVjdGFuZ2xlXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHBhaW50ZXIuZGVidWdCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z0J1ZmZlci5pdGVtU2l6ZSwgZ2wuU0hPUlQsIGZhbHNlLCAwLCAwKTtcbiAgICBnbC51bmlmb3JtNGYocGFpbnRlci5kZWJ1Z1NoYWRlci51X2NvbG9yLCAxLCAwLCAwLCAxKTtcbiAgICBnbC5saW5lV2lkdGgoNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FX1NUUklQLCAwLCBwYWludGVyLmRlYnVnQnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICB2YXIgdmVydGljZXMgPSB0ZXh0VmVydGljZXModGlsZS5jb29yZC50b1N0cmluZygpLCA1MCwgMjAwLCA1KTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBwYWludGVyLmRlYnVnVGV4dEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBJbnQxNkFycmF5KHZlcnRpY2VzKSwgZ2wuU1RSRUFNX0RSQVcpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kZWJ1Z1NoYWRlci5hX3BvcywgcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wubGluZVdpZHRoKDggKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIGdsLnVuaWZvcm00ZihwYWludGVyLmRlYnVnU2hhZGVyLnVfY29sb3IsIDEsIDEsIDEsIDEpO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHZlcnRpY2VzLmxlbmd0aCAvIHBhaW50ZXIuZGVidWdUZXh0QnVmZmVyLml0ZW1TaXplKTtcbiAgICBnbC5saW5lV2lkdGgoMiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgZ2wudW5pZm9ybTRmKHBhaW50ZXIuZGVidWdTaGFkZXIudV9jb2xvciwgMCwgMCwgMCwgMSk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdmVydGljZXMubGVuZ3RoIC8gcGFpbnRlci5kZWJ1Z1RleHRCdWZmZXIuaXRlbVNpemUpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0MyA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDM7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd0ZpbGw7XG5cbmZ1bmN0aW9uIGRyYXdGaWxsKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpIHtcbiAgICAvLyBObyBkYXRhXG4gICAgaWYgKCF0aWxlLmJ1ZmZlcnMpIHJldHVybjtcbiAgICB2YXIgZWxlbWVudEdyb3VwcyA9IHRpbGUuZWxlbWVudEdyb3Vwc1tsYXllci5yZWYgfHwgbGF5ZXIuaWRdO1xuICAgIGlmICghZWxlbWVudEdyb3VwcykgcmV0dXJuO1xuXG4gICAgdmFyIGdsID0gcGFpbnRlci5nbDtcbiAgICB2YXIgdHJhbnNsYXRlZFBvc01hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2ZpbGwtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydmaWxsLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgY29sb3IgPSBsYXllci5wYWludFsnZmlsbC1jb2xvciddO1xuXG4gICAgdmFyIHZlcnRleCwgZWxlbWVudHMsIGdyb3VwLCBjb3VudDtcblxuICAgIC8vIERyYXcgdGhlIHN0ZW5jaWwgbWFzay5cblxuICAgIC8vIFdlJ3JlIG9ubHkgZHJhd2luZyB0byB0aGUgZmlyc3Qgc2V2ZW4gYml0cyAoPT0gc3VwcG9ydCBhIG1heGltdW0gb2ZcbiAgICAvLyAxMjcgb3ZlcmxhcHBpbmcgcG9seWdvbnMgaW4gb25lIHBsYWNlIGJlZm9yZSB3ZSBnZXQgcmVuZGVyaW5nIGVycm9ycykuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgzRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIERyYXcgZnJvbnQgZmFjaW5nIHRyaWFuZ2xlcy4gV2hlcmV2ZXIgdGhlIDB4ODAgYml0IGlzIDEsIHdlIGFyZVxuICAgIC8vIGluY3JlYXNpbmcgdGhlIGxvd2VyIDcgYml0cyBieSBvbmUgaWYgdGhlIHRyaWFuZ2xlIGlzIGEgZnJvbnQtZmFjaW5nXG4gICAgLy8gdHJpYW5nbGUuIFRoaXMgbWVhbnMgdGhhdCBhbGwgdmlzaWJsZSBwb2x5Z29ucyBzaG91bGQgYmUgaW4gQ0NXXG4gICAgLy8gb3JpZW50YXRpb24sIHdoaWxlIGFsbCBob2xlcyAoc2VlIGJlbG93KSBhcmUgaW4gQ1cgb3JpZW50YXRpb24uXG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuTk9URVFVQUwsIDB4ODAsIDB4ODApO1xuXG4gICAgLy8gV2hlbiB3ZSBkbyBhIG5vbnplcm8gZmlsbCwgd2UgY291bnQgdGhlIG51bWJlciBvZiB0aW1lcyBhIHBpeGVsIGlzXG4gICAgLy8gY292ZXJlZCBieSBhIGNvdW50ZXJjbG9ja3dpc2UgcG9seWdvbiwgYW5kIHN1YnRyYWN0IHRoZSBudW1iZXIgb2ZcbiAgICAvLyB0aW1lcyBpdCBpcyBcInVuY292ZXJlZFwiIGJ5IGEgY2xvY2t3aXNlIHBvbHlnb24uXG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuRlJPTlQsIGdsLklOQ1JfV1JBUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE9wU2VwYXJhdGUoZ2wuQkFDSywgZ2wuREVDUl9XUkFQLCBnbC5LRUVQLCBnbC5LRUVQKTtcblxuICAgIC8vIFdoZW4gZHJhd2luZyBhIHNoYXBlLCB3ZSBmaXJzdCBkcmF3IGFsbCBzaGFwZXMgdG8gdGhlIHN0ZW5jaWwgYnVmZmVyXG4gICAgLy8gYW5kIGluY3JlbWVudGluZyBhbGwgYXJlYXMgd2hlcmUgcG9seWdvbnMgYXJlXG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIERyYXcgdGhlIGFjdHVhbCB0cmlhbmdsZSBmYW4gaW50byB0aGUgc3RlbmNpbCBidWZmZXIuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZmlsbFNoYWRlciwgdHJhbnNsYXRlZFBvc01hdHJpeCk7XG5cbiAgICAvLyBEcmF3IGFsbCBidWZmZXJzXG4gICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgdmVydGV4LmJpbmQoZ2wpO1xuICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmZpbGxFbGVtZW50O1xuICAgIGVsZW1lbnRzLmJpbmQoZ2wpO1xuXG4gICAgdmFyIG9mZnNldCwgZWxlbWVudE9mZnNldDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwYWludGVyLmZpbGxTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgNCwgb2Zmc2V0ICsgMCk7XG5cbiAgICAgICAgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgc3RlbmNpbCBtYXNrIGluIHRoZSBzdGVuY2lsIGJ1ZmZlciwgd2UgY2FuIHN0YXJ0XG4gICAgLy8gd3JpdGluZyB0byB0aGUgY29sb3IgYnVmZmVyLlxuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcblxuICAgIC8vIEZyb20gbm93IG9uLCB3ZSBkb24ndCB3YW50IHRvIHVwZGF0ZSB0aGUgc3RlbmNpbCBidWZmZXIgYW55bW9yZS5cbiAgICBnbC5zdGVuY2lsT3AoZ2wuS0VFUCwgZ2wuS0VFUCwgZ2wuS0VFUCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwKTtcblxuICAgIHZhciBzdHJva2VDb2xvciA9IGxheWVyLnBhaW50WydmaWxsLW91dGxpbmUtY29sb3InXTtcblxuICAgIC8vIEJlY2F1c2Ugd2UncmUgZHJhd2luZyB0b3AtdG8tYm90dG9tLCBhbmQgd2UgdXBkYXRlIHRoZSBzdGVuY2lsIG1hc2tcbiAgICAvLyBiZWxvdywgd2UgaGF2ZSB0byBkcmF3IHRoZSBvdXRsaW5lIGZpcnN0ICghKVxuICAgIGlmIChsYXllci5wYWludFsnZmlsbC1hbnRpYWxpYXMnXSA9PT0gdHJ1ZSAmJiAhKGxheWVyLnBhaW50WydmaWxsLWltYWdlJ10gJiYgIXN0cm9rZUNvbG9yKSkge1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLCB0cmFuc2xhdGVkUG9zTWF0cml4KTtcbiAgICAgICAgZ2wubGluZVdpZHRoKDIgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuXG4gICAgICAgIGlmIChzdHJva2VDb2xvcikge1xuICAgICAgICAgICAgLy8gSWYgd2UgZGVmaW5lZCBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGZpbGwgb3V0bGluZSwgd2UgYXJlXG4gICAgICAgICAgICAvLyBnb2luZyB0byBpZ25vcmUgdGhlIGJpdHMgaW4gMHgzRiBhbmQganVzdCBjYXJlIGFib3V0IHRoZSBnbG9iYWxcbiAgICAgICAgICAgIC8vIGNsaXBwaW5nIG1hc2suXG4gICAgICAgICAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIG9ubHkgd2FudCB0byBkcmF3IHRoZSBhbnRpYWxpYXNlZCBwYXJ0cyB0aGF0IGFyZVxuICAgICAgICAgICAgLy8gKm91dHNpZGUqIHRoZSBjdXJyZW50IHNoYXBlLiBUaGlzIGlzIGltcG9ydGFudCBpbiBjYXNlIHRoZSBmaWxsXG4gICAgICAgICAgICAvLyBvciBzdHJva2UgY29sb3IgaXMgdHJhbnNsdWNlbnQuIElmIHdlIHdvdWxkbid0IGNsaXAgdG8gb3V0c2lkZVxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgc2hhcGUsIHNvbWUgcGl4ZWxzIGZyb20gdGhlIG91dGxpbmUgc3Ryb2tlIG92ZXJsYXBwZWRcbiAgICAgICAgICAgIC8vIHRoZSAobm9uLWFudGlhbGlhc2VkKSBmaWxsLlxuICAgICAgICAgICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4QkYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmKHBhaW50ZXIub3V0bGluZVNoYWRlci51X3dvcmxkLCBnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHBhaW50ZXIub3V0bGluZVNoYWRlci51X2NvbG9yLCBzdHJva2VDb2xvciA/IHN0cm9rZUNvbG9yIDogY29sb3IpO1xuXG4gICAgICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICAgICAgdmVydGV4ID0gdGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLm91dGxpbmVFbGVtZW50O1xuICAgICAgICBlbGVtZW50cy5iaW5kKGdsKTtcblxuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5vdXRsaW5lU2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDQsIG9mZnNldCArIDApO1xuXG4gICAgICAgICAgICBjb3VudCA9IGdyb3VwLnNlY29uZEVsZW1lbnRMZW5ndGggKiAyO1xuICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLnNlY29uZEVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICBnbC5kcmF3RWxlbWVudHMoZ2wuTElORVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnZmlsbC1pbWFnZSddO1xuICAgIHZhciBvcGFjaXR5ID0gbGF5ZXIucGFpbnRbJ2ZpbGwtb3BhY2l0eSddIHx8IDE7XG4gICAgdmFyIHNoYWRlcjtcblxuICAgIGlmIChpbWFnZSkge1xuICAgICAgICAvLyBEcmF3IHRleHR1cmUgZmlsbFxuICAgICAgICB2YXIgaW1hZ2VQb3NBID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS5mcm9tLCB0cnVlKTtcbiAgICAgICAgdmFyIGltYWdlUG9zQiA9IHBhaW50ZXIuc3ByaXRlQXRsYXMuZ2V0UG9zaXRpb24oaW1hZ2UudG8sIHRydWUpO1xuICAgICAgICBpZiAoIWltYWdlUG9zQSB8fCAhaW1hZ2VQb3NCKSByZXR1cm47XG5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5wYXR0ZXJuU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtMWkoc2hhZGVyLnVfaW1hZ2UsIDApO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYSwgaW1hZ2VQb3NBLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2EsIGltYWdlUG9zQS5icik7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl90bF9iLCBpbWFnZVBvc0IudGwpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fYnJfYiwgaW1hZ2VQb3NCLmJyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIG9wYWNpdHkpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBpbWFnZS50KTtcblxuICAgICAgICB2YXIgZmFjdG9yID0gKHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUpIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0udGlsZVpvb20gLSB0aWxlLmNvb3JkLnopO1xuXG4gICAgICAgIHZhciBtYXRyaXhBID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhBLCBtYXRyaXhBLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQS5zaXplWzBdICogZmFjdG9yICogaW1hZ2UuZnJvbVNjYWxlKSxcbiAgICAgICAgICAgIDEgLyAoaW1hZ2VQb3NBLnNpemVbMV0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUpXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHZhciBtYXRyaXhCID0gbWF0My5jcmVhdGUoKTtcbiAgICAgICAgbWF0My5zY2FsZShtYXRyaXhCLCBtYXRyaXhCLCBbXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzBdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSksXG4gICAgICAgICAgICAxIC8gKGltYWdlUG9zQi5zaXplWzFdICogZmFjdG9yICogaW1hZ2UudG9TY2FsZSlcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2EsIGZhbHNlLCBtYXRyaXhBKTtcbiAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDNmdihzaGFkZXIudV9wYXR0ZXJubWF0cml4X2IsIGZhbHNlLCBtYXRyaXhCKTtcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRHJhdyBmaWxsaW5nIHJlY3RhbmdsZS5cbiAgICAgICAgc2hhZGVyID0gcGFpbnRlci5maWxsU2hhZGVyO1xuICAgICAgICBnbC5zd2l0Y2hTaGFkZXIoc2hhZGVyLCBwb3NNYXRyaXgpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgLy8gT25seSBkcmF3IHJlZ2lvbnMgdGhhdCB3ZSBtYXJrZWRcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5OT1RFUVVBTCwgMHgwLCAweDNGKTtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyKTtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgcGFpbnRlci50aWxlRXh0ZW50QnVmZmVyLml0ZW1TaXplLCBnbC5TSE9SVCwgZmFsc2UsIDAsIDApO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgZ2wuc3RlbmNpbE1hc2soMHgwMCk7XG4gICAgZ2wuc3RlbmNpbEZ1bmMoZ2wuRVFVQUwsIDB4ODAsIDB4ODApO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDIgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQyO1xuXG4vKipcbiAqIERyYXcgYSBsaW5lLiBVbmRlciB0aGUgaG9vZCB0aGlzIHdpbGwgcmVhZCBlbGVtZW50cyBmcm9tXG4gKiBhIHRpbGUsIGRhc2ggdGV4dHVyZXMgZnJvbSBhIGxpbmVBdGxhcywgYW5kIHN0eWxlIHByb3BlcnRpZXMgZnJvbSBhIGxheWVyLlxuICogQHBhcmFtIHtPYmplY3R9IHBhaW50ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXllclxuICogQHBhcmFtIHtPYmplY3R9IHBvc01hdHJpeFxuICogQHBhcmFtIHtUaWxlfSB0aWxlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBkcmF3cyB3aXRoIHRoZSBwYWludGVyXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhd0xpbmUocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuXG4gICAgLy8gZG9uJ3QgZHJhdyB6ZXJvLXdpZHRoIGxpbmVzXG4gICAgaWYgKGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ10gPD0gMCkgcmV0dXJuO1xuXG4gICAgLy8gdGhlIGRpc3RhbmNlIG92ZXIgd2hpY2ggdGhlIGxpbmUgZWRnZSBmYWRlcyBvdXQuXG4gICAgLy8gUmV0aW5hIGRldmljZXMgbmVlZCBhIHNtYWxsZXIgZGlzdGFuY2UgdG8gYXZvaWQgYWxpYXNpbmcuXG4gICAgdmFyIGFudGlhbGlhc2luZyA9IDEgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICB2YXIgYmx1ciA9IGxheWVyLnBhaW50WydsaW5lLWJsdXInXSArIGFudGlhbGlhc2luZztcbiAgICB2YXIgZWRnZVdpZHRoID0gbGF5ZXIucGFpbnRbJ2xpbmUtd2lkdGgnXSAvIDI7XG4gICAgdmFyIGluc2V0ID0gLTE7XG4gICAgdmFyIG9mZnNldCA9IDA7XG4gICAgdmFyIHNoaWZ0ID0gMDtcblxuICAgIGlmIChsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSA+IDApIHtcbiAgICAgICAgaW5zZXQgPSBsYXllci5wYWludFsnbGluZS1nYXAtd2lkdGgnXSAvIDIgKyBhbnRpYWxpYXNpbmcgKiAwLjU7XG4gICAgICAgIGVkZ2VXaWR0aCA9IGxheWVyLnBhaW50WydsaW5lLXdpZHRoJ107XG5cbiAgICAgICAgLy8gc2hpZnQgb3V0ZXIgbGluZXMgaGFsZiBhIHBpeGVsIHRvd2FyZHMgdGhlIG1pZGRsZSB0byBlbGltaW5hdGUgdGhlIGNyYWNrXG4gICAgICAgIG9mZnNldCA9IGluc2V0IC0gYW50aWFsaWFzaW5nIC8gMjtcbiAgICB9XG5cbiAgICB2YXIgb3V0c2V0ID0gb2Zmc2V0ICsgZWRnZVdpZHRoICsgYW50aWFsaWFzaW5nIC8gMiArIHNoaWZ0O1xuXG4gICAgdmFyIGNvbG9yID0gbGF5ZXIucGFpbnRbJ2xpbmUtY29sb3InXTtcbiAgICB2YXIgcmF0aW8gPSBwYWludGVyLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHZ0eE1hdHJpeCA9IHBhaW50ZXIudHJhbnNsYXRlTWF0cml4KHBvc01hdHJpeCwgdGlsZSwgbGF5ZXIucGFpbnRbJ2xpbmUtdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50WydsaW5lLXRyYW5zbGF0ZS1hbmNob3InXSk7XG5cbiAgICB2YXIgdHIgPSBwYWludGVyLnRyYW5zZm9ybTtcblxuXG4gICAgdmFyIGFudGlhbGlhc2luZ01hdHJpeCA9IG1hdDIuY3JlYXRlKCk7XG4gICAgbWF0Mi5zY2FsZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgWzEsIE1hdGguY29zKHRyLl9waXRjaCldKTtcbiAgICBtYXQyLnJvdGF0ZShhbnRpYWxpYXNpbmdNYXRyaXgsIGFudGlhbGlhc2luZ01hdHJpeCwgcGFpbnRlci50cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIGxvbmdlciB0aGUgcmVhbCB3b3JsZCBkaXN0YW5jZSBpcyBhdCB0aGUgdG9wIG9mIHRoZSBzY3JlZW5cbiAgICAvLyB0aGFuIGF0IHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbi5cbiAgICB2YXIgdG9wZWRnZWxlbmd0aCA9IE1hdGguc3FydCh0ci5oZWlnaHQgKiB0ci5oZWlnaHQgLyA0ICAqICgxICsgdHIuYWx0aXR1ZGUgKiB0ci5hbHRpdHVkZSkpO1xuICAgIHZhciB4ID0gdHIuaGVpZ2h0IC8gMiAqIE1hdGgudGFuKHRyLl9waXRjaCk7XG4gICAgdmFyIGV4dHJhID0gKHRvcGVkZ2VsZW5ndGggKyB4KSAvIHRvcGVkZ2VsZW5ndGggLSAxO1xuXG4gICAgLy8gaG93IG11Y2ggdGhlIHRpbGUgaXMgb3ZlcnNjYWxlZCBieVxuICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUudGlsZVNpemUgLyBwYWludGVyLnRyYW5zZm9ybS50aWxlU2l6ZTtcblxuICAgIHZhciBzaGFkZXI7XG5cblxuICAgIHZhciBkYXNoYXJyYXkgPSBsYXllci5wYWludFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICB2YXIgaW1hZ2UgPSBsYXllci5wYWludFsnbGluZS1pbWFnZSddO1xuXG4gICAgaWYgKGRhc2hhcnJheSkge1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXNkZnBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgY29sb3IpO1xuXG4gICAgICAgIHZhciBwb3NBID0gcGFpbnRlci5saW5lQXRsYXMuZ2V0RGFzaChkYXNoYXJyYXkuZnJvbSwgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgdmFyIHBvc0IgPSBwYWludGVyLmxpbmVBdGxhcy5nZXREYXNoKGRhc2hhcnJheS50bywgbGF5ZXIubGF5b3V0WydsaW5lLWNhcCddID09PSAncm91bmQnKTtcbiAgICAgICAgcGFpbnRlci5saW5lQXRsYXMuYmluZChnbCk7XG5cbiAgICAgICAgdmFyIHBhdHRlcm5yYXRpbyA9IE1hdGgucG93KDIsIE1hdGguZmxvb3IoTWF0aC5sb2cocGFpbnRlci50cmFuc2Zvcm0uc2NhbGUpIC8gTWF0aC5MTjIpIC0gdGlsZS5jb29yZC56KSAvIDggKiBvdmVyc2NhbGluZztcbiAgICAgICAgdmFyIHNjYWxlQSA9IFtwYXR0ZXJucmF0aW8gLyBwb3NBLndpZHRoIC8gZGFzaGFycmF5LmZyb21TY2FsZSwgLXBvc0EuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUEgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkuZnJvbVNjYWxlICogcG9zQS53aWR0aCAqIDI1NiAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbykgLyAyO1xuICAgICAgICB2YXIgc2NhbGVCID0gW3BhdHRlcm5yYXRpbyAvIHBvc0Iud2lkdGggLyBkYXNoYXJyYXkudG9TY2FsZSwgLXBvc0IuaGVpZ2h0IC8gMl07XG4gICAgICAgIHZhciBnYW1tYUIgPSBwYWludGVyLmxpbmVBdGxhcy53aWR0aCAvIChkYXNoYXJyYXkudG9TY2FsZSAqIHBvc0Iud2lkdGggKiAyNTYgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pIC8gMjtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5zY2FsZV9hLCBzY2FsZUEpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfdGV4X3lfYSwgcG9zQS55KTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuc2NhbGVfYiwgc2NhbGVCKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3RleF95X2IsIHBvc0IueSk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X2ltYWdlLCAwKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NkZmdhbW1hLCBNYXRoLm1heChnYW1tYUEsIGdhbW1hQikpO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWl4LCBkYXNoYXJyYXkudCk7XG5cbiAgICB9IGVsc2UgaWYgKGltYWdlKSB7XG4gICAgICAgIHZhciBpbWFnZVBvc0EgPSBwYWludGVyLnNwcml0ZUF0bGFzLmdldFBvc2l0aW9uKGltYWdlLmZyb20sIHRydWUpO1xuICAgICAgICB2YXIgaW1hZ2VQb3NCID0gcGFpbnRlci5zcHJpdGVBdGxhcy5nZXRQb3NpdGlvbihpbWFnZS50bywgdHJ1ZSk7XG4gICAgICAgIGlmICghaW1hZ2VQb3NBIHx8ICFpbWFnZVBvc0IpIHJldHVybjtcbiAgICAgICAgdmFyIGZhY3RvciA9IHRpbGUudGlsZUV4dGVudCAvIHRpbGUudGlsZVNpemUgLyBNYXRoLnBvdygyLCBwYWludGVyLnRyYW5zZm9ybS50aWxlWm9vbSAtIHRpbGUuY29vcmQueikgKiBvdmVyc2NhbGluZztcblxuICAgICAgICBwYWludGVyLnNwcml0ZUF0bGFzLmJpbmQoZ2wsIHRydWUpO1xuXG4gICAgICAgIHNoYWRlciA9IHBhaW50ZXIubGluZXBhdHRlcm5TaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcblxuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9hLCBbaW1hZ2VQb3NBLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS5mcm9tU2NhbGUsIGltYWdlUG9zQi5zaXplWzFdIF0pO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fc2l6ZV9iLCBbaW1hZ2VQb3NCLnNpemVbMF0gKiBmYWN0b3IgKiBpbWFnZS50b1NjYWxlLCBpbWFnZVBvc0Iuc2l6ZVsxXSBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX3RsX2EsIGltYWdlUG9zQS50bCk7XG4gICAgICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfcGF0dGVybl9icl9hLCBpbWFnZVBvc0EuYnIpO1xuICAgICAgICBnbC51bmlmb3JtMmZ2KHNoYWRlci51X3BhdHRlcm5fdGxfYiwgaW1hZ2VQb3NCLnRsKTtcbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9wYXR0ZXJuX2JyX2IsIGltYWdlUG9zQi5icik7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlLCBpbWFnZS50KTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHksIGxheWVyLnBhaW50WydsaW5lLW9wYWNpdHknXSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmxpbmVTaGFkZXI7XG4gICAgICAgIGdsLnN3aXRjaFNoYWRlcihzaGFkZXIsIHZ0eE1hdHJpeCwgdGlsZS5leE1hdHJpeCk7XG5cbiAgICAgICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV9saW5ld2lkdGgsIFsgb3V0c2V0LCBpbnNldCBdKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3JhdGlvLCByYXRpbyk7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9ibHVyLCBibHVyKTtcbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2V4dHJhLCBleHRyYSk7XG4gICAgICAgIGdsLnVuaWZvcm1NYXRyaXgyZnYoc2hhZGVyLnVfYW50aWFsaWFzaW5nbWF0cml4LCBmYWxzZSwgYW50aWFsaWFzaW5nTWF0cml4KTtcblxuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBjb2xvcik7XG4gICAgfVxuXG4gICAgdmFyIHZlcnRleCA9IHRpbGUuYnVmZmVycy5saW5lVmVydGV4O1xuICAgIHZlcnRleC5iaW5kKGdsKTtcbiAgICB2YXIgZWxlbWVudCA9IHRpbGUuYnVmZmVycy5saW5lRWxlbWVudDtcbiAgICBlbGVtZW50LmJpbmQoZ2wpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50R3JvdXBzLmdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXAgPSBlbGVtZW50R3JvdXBzLmdyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHZ0eE9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfcG9zLCAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIHZ0eE9mZnNldCArIDApO1xuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX2RhdGEsIDQsIGdsLkJZVEUsIGZhbHNlLCA4LCB2dHhPZmZzZXQgKyA0KTtcblxuICAgICAgICB2YXIgY291bnQgPSBncm91cC5lbGVtZW50TGVuZ3RoICogMztcbiAgICAgICAgdmFyIGVsZW1lbnRPZmZzZXQgPSBncm91cC5lbGVtZW50U3RhcnRJbmRleCAqIGVsZW1lbnQuaXRlbVNpemU7XG4gICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgfVxuXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRyYXdSYXN0ZXI7XG5cbmZ1bmN0aW9uIGRyYXdSYXN0ZXIocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG5cbiAgICB2YXIgc2hhZGVyID0gcGFpbnRlci5yYXN0ZXJTaGFkZXI7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4KTtcblxuICAgIC8vIGNvbG9yIHBhcmFtZXRlcnNcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnJpZ2h0bmVzc19sb3csIGxheWVyLnBhaW50WydyYXN0ZXItYnJpZ2h0bmVzcy1taW4nXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2JyaWdodG5lc3NfaGlnaCwgbGF5ZXIucGFpbnRbJ3Jhc3Rlci1icmlnaHRuZXNzLW1heCddKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfc2F0dXJhdGlvbl9mYWN0b3IsIHNhdHVyYXRpb25GYWN0b3IobGF5ZXIucGFpbnRbJ3Jhc3Rlci1zYXR1cmF0aW9uJ10pKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfY29udHJhc3RfZmFjdG9yLCBjb250cmFzdEZhY3RvcihsYXllci5wYWludFsncmFzdGVyLWNvbnRyYXN0J10pKTtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlci51X3NwaW5fd2VpZ2h0cywgc3BpbldlaWdodHMobGF5ZXIucGFpbnRbJ3Jhc3Rlci1odWUtcm90YXRlJ10pKTtcblxuICAgIHZhciBwYXJlbnRUaWxlID0gdGlsZS5zb3VyY2UgJiYgdGlsZS5zb3VyY2UuX3B5cmFtaWQuZmluZExvYWRlZFBhcmVudCh0aWxlLmNvb3JkLCAwLCB7fSksXG4gICAgICAgIG9wYWNpdGllcyA9IGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgcGFpbnRlci50cmFuc2Zvcm0pO1xuXG4gICAgdmFyIHBhcmVudFNjYWxlQnksIHBhcmVudFRMO1xuXG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCk7XG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcblxuICAgIGlmIChwYXJlbnRUaWxlKSB7XG4gICAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTEpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBwYXJlbnRUaWxlLnRleHR1cmUpO1xuXG4gICAgICAgIHBhcmVudFNjYWxlQnkgPSBNYXRoLnBvdygyLCBwYXJlbnRUaWxlLmNvb3JkLnogLSB0aWxlLmNvb3JkLnopO1xuICAgICAgICBwYXJlbnRUTCA9IFt0aWxlLmNvb3JkLnggKiBwYXJlbnRTY2FsZUJ5ICUgMSwgdGlsZS5jb29yZC55ICogcGFyZW50U2NhbGVCeSAlIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wYWNpdGllc1sxXSA9IDA7XG4gICAgfVxuXG4gICAgLy8gY3Jvc3MtZmFkZSBwYXJhbWV0ZXJzXG4gICAgZ2wudW5pZm9ybTJmdihzaGFkZXIudV90bF9wYXJlbnQsIHBhcmVudFRMIHx8IFswLCAwXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3NjYWxlX3BhcmVudCwgcGFyZW50U2NhbGVCeSB8fCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyX3NjYWxlLCAxKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfb3BhY2l0eTAsIG9wYWNpdGllc1swXSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X29wYWNpdHkxLCBvcGFjaXRpZXNbMV0pO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTAsIDApO1xuICAgIGdsLnVuaWZvcm0xaShzaGFkZXIudV9pbWFnZTEsIDEpO1xuXG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRpbGUuYm91bmRzQnVmZmVyIHx8IHBhaW50ZXIudGlsZUV4dGVudEJ1ZmZlcik7XG5cbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHNoYWRlci5hX3BvcywgICAgICAgICAyLCBnbC5TSE9SVCwgZmFsc2UsIDgsIDApO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoc2hhZGVyLmFfdGV4dHVyZV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgOCwgNCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cbiAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbn1cblxuZnVuY3Rpb24gc3BpbldlaWdodHMoYW5nbGUpIHtcbiAgICBhbmdsZSAqPSBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBzID0gTWF0aC5zaW4oYW5nbGUpO1xuICAgIHZhciBjID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHJldHVybiBbXG4gICAgICAgICgyICogYyArIDEpIC8gMyxcbiAgICAgICAgKC1NYXRoLnNxcnQoMykgKiBzIC0gYyArIDEpIC8gMyxcbiAgICAgICAgKE1hdGguc3FydCgzKSAqIHMgLSBjICsgMSkgLyAzXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gY29udHJhc3RGYWN0b3IoY29udHJhc3QpIHtcbiAgICByZXR1cm4gY29udHJhc3QgPiAwID9cbiAgICAgICAgMSAvICgxIC0gY29udHJhc3QpIDpcbiAgICAgICAgMSArIGNvbnRyYXN0O1xufVxuXG5mdW5jdGlvbiBzYXR1cmF0aW9uRmFjdG9yKHNhdHVyYXRpb24pIHtcbiAgICByZXR1cm4gc2F0dXJhdGlvbiA+IDAgP1xuICAgICAgICAxIC0gMSAvICgxLjAwMSAtIHNhdHVyYXRpb24pIDpcbiAgICAgICAgLXNhdHVyYXRpb247XG59XG5cbmZ1bmN0aW9uIGdldE9wYWNpdGllcyh0aWxlLCBwYXJlbnRUaWxlLCBsYXllciwgdHJhbnNmb3JtKSB7XG4gICAgaWYgKCF0aWxlLnNvdXJjZSkgcmV0dXJuIFsxLCAwXTtcblxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIHZhciBmYWRlRHVyYXRpb24gPSBsYXllci5wYWludFsncmFzdGVyLWZhZGUtZHVyYXRpb24nXTtcbiAgICB2YXIgc2luY2VUaWxlID0gKG5vdyAtIHRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbjtcbiAgICB2YXIgc2luY2VQYXJlbnQgPSBwYXJlbnRUaWxlID8gKG5vdyAtIHBhcmVudFRpbGUudGltZUFkZGVkKSAvIGZhZGVEdXJhdGlvbiA6IC0xO1xuXG4gICAgdmFyIGlkZWFsWiA9IHRpbGUuc291cmNlLl9weXJhbWlkLmNvdmVyaW5nWm9vbUxldmVsKHRyYW5zZm9ybSk7XG4gICAgdmFyIHBhcmVudEZ1cnRoZXIgPSBwYXJlbnRUaWxlID8gTWF0aC5hYnMocGFyZW50VGlsZS5jb29yZC56IC0gaWRlYWxaKSA+IE1hdGguYWJzKHRpbGUuY29vcmQueiAtIGlkZWFsWikgOiBmYWxzZTtcblxuICAgIHZhciBvcGFjaXR5ID0gW107XG4gICAgaWYgKCFwYXJlbnRUaWxlIHx8IHBhcmVudEZ1cnRoZXIpIHtcbiAgICAgICAgLy8gaWYgbm8gcGFyZW50IG9yIHBhcmVudCBpcyBvbGRlclxuICAgICAgICBvcGFjaXR5WzBdID0gdXRpbC5jbGFtcChzaW5jZVRpbGUsIDAsIDEpO1xuICAgICAgICBvcGFjaXR5WzFdID0gMSAtIG9wYWNpdHlbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyZW50IGlzIHlvdW5nZXIsIHpvb21pbmcgb3V0XG4gICAgICAgIG9wYWNpdHlbMF0gPSB1dGlsLmNsYW1wKDEgLSBzaW5jZVBhcmVudCwgMCwgMSk7XG4gICAgICAgIG9wYWNpdHlbMV0gPSAxIC0gb3BhY2l0eVswXTtcbiAgICB9XG5cbiAgICB2YXIgb3AgPSBsYXllci5wYWludFsncmFzdGVyLW9wYWNpdHknXTtcbiAgICBvcGFjaXR5WzBdICo9IG9wO1xuICAgIG9wYWNpdHlbMV0gKj0gb3A7XG5cbiAgICByZXR1cm4gb3BhY2l0eTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBtYXQ0ID0gcmVxdWlyZSgnZ2wtbWF0cml4JykubWF0NDtcblxudmFyIGRyYXdDb2xsaXNpb25EZWJ1ZyA9IHJlcXVpcmUoJy4vZHJhd19jb2xsaXNpb25fZGVidWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkcmF3U3ltYm9scztcblxuZnVuY3Rpb24gZHJhd1N5bWJvbHMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIC8vIE5vIGRhdGFcbiAgICBpZiAoIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICB2YXIgZHJhd0Fjcm9zc0VkZ2VzID0gIShsYXllci5sYXlvdXRbJ3RleHQtYWxsb3ctb3ZlcmxhcCddIHx8IGxheWVyLmxheW91dFsnaWNvbi1hbGxvdy1vdmVybGFwJ10gfHxcbiAgICAgICAgbGF5ZXIubGF5b3V0Wyd0ZXh0LWlnbm9yZS1wbGFjZW1lbnQnXSB8fCBsYXllci5sYXlvdXRbJ2ljb24taWdub3JlLXBsYWNlbWVudCddKTtcblxuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoZHJhd0Fjcm9zc0VkZ2VzKSB7XG4gICAgICAgIC8vIERpc2FibGUgdGhlIHN0ZW5jaWwgdGVzdCBzbyB0aGF0IGxhYmVscyBhcmVuJ3QgY2xpcHBlZCB0byB0aWxlIGJvdW5kYXJpZXMuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIExheWVycyB3aXRoIGZlYXR1cmVzIHRoYXQgbWF5IGJlIGRyYXduIG92ZXJsYXBwaW5nIGFyZW4ndCBjbGlwcGVkLiBUaGVzZVxuICAgICAgICAvLyBsYXllcnMgYXJlIHNvcnRlZCBpbiB0aGUgeSBkaXJlY3Rpb24sIGFuZCB0byBkcmF3IHRoZSBjb3JyZWN0IG9yZGVyaW5nIG5lYXJcbiAgICAgICAgLy8gdGlsZSBlZGdlcyB0aGUgaWNvbnMgYXJlIGluY2x1ZGVkIGluIGJvdGggdGlsZXMgYW5kIGNsaXBwZWQgd2hlbiBkcmF3aW5nLlxuICAgICAgICBnbC5kaXNhYmxlKGdsLlNURU5DSUxfVEVTVCk7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRHcm91cHMudGV4dC5ncm91cHMubGVuZ3RoKSB7XG4gICAgICAgIGRyYXdTeW1ib2wocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSwgZWxlbWVudEdyb3Vwcy50ZXh0LCAndGV4dCcsIHRydWUpO1xuICAgIH1cbiAgICBpZiAoZWxlbWVudEdyb3Vwcy5pY29uLmdyb3Vwcy5sZW5ndGgpIHtcbiAgICAgICAgZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLmljb24sICdpY29uJywgZWxlbWVudEdyb3Vwcy5zZGZJY29ucyk7XG4gICAgfVxuXG4gICAgZHJhd0NvbGxpc2lvbkRlYnVnKHBhaW50ZXIsIGxheWVyLCBwb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKGRyYXdBY3Jvc3NFZGdlcykge1xuICAgICAgICBnbC5lbmFibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0U2l6ZXMgPSB7XG4gICAgaWNvbjogMSxcbiAgICB0ZXh0OiAyNFxufTtcblxuZnVuY3Rpb24gZHJhd1N5bWJvbChwYWludGVyLCBsYXllciwgcG9zTWF0cml4LCB0aWxlLCBlbGVtZW50R3JvdXBzLCBwcmVmaXgsIHNkZikge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBwb3NNYXRyaXggPSBwYWludGVyLnRyYW5zbGF0ZU1hdHJpeChwb3NNYXRyaXgsIHRpbGUsIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlJ10sIGxheWVyLnBhaW50W3ByZWZpeCArICctdHJhbnNsYXRlLWFuY2hvciddKTtcblxuICAgIHZhciB0ciA9IHBhaW50ZXIudHJhbnNmb3JtO1xuICAgIHZhciBhbGlnbmVkV2l0aE1hcCA9IGxheWVyLmxheW91dFtwcmVmaXggKyAnLXJvdGF0aW9uLWFsaWdubWVudCddID09PSAnbWFwJztcbiAgICB2YXIgc2tld2VkID0gYWxpZ25lZFdpdGhNYXA7XG4gICAgdmFyIGV4TWF0cml4LCBzLCBnYW1tYVNjYWxlO1xuXG4gICAgaWYgKHNrZXdlZCkge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIHMgPSB0aWxlLnRpbGVFeHRlbnQgLyB0aWxlLnRpbGVTaXplIC8gTWF0aC5wb3coMiwgcGFpbnRlci50cmFuc2Zvcm0uem9vbSAtIHRpbGUuY29vcmQueik7XG4gICAgICAgIGdhbW1hU2NhbGUgPSAxIC8gTWF0aC5jb3ModHIuX3BpdGNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBleE1hdHJpeCA9IG1hdDQuY2xvbmUodGlsZS5leE1hdHJpeCk7XG4gICAgICAgIHMgPSBwYWludGVyLnRyYW5zZm9ybS5hbHRpdHVkZTtcbiAgICAgICAgZ2FtbWFTY2FsZSA9IDE7XG4gICAgfVxuICAgIG1hdDQuc2NhbGUoZXhNYXRyaXgsIGV4TWF0cml4LCBbcywgcywgMV0pO1xuXG4gICAgLy8gSWYgbGF5ZXIucGFpbnQuc2l6ZSA+IGxheWVyLmxheW91dFtwcmVmaXggKyAnLW1heC1zaXplJ10gdGhlbiBsYWJlbHMgbWF5IGNvbGxpZGVcbiAgICB2YXIgZm9udFNpemUgPSBsYXllci5wYWludFtwcmVmaXggKyAnLXNpemUnXTtcbiAgICB2YXIgZm9udFNjYWxlID0gZm9udFNpemUgLyBkZWZhdWx0U2l6ZXNbcHJlZml4XTtcbiAgICBtYXQ0LnNjYWxlKGV4TWF0cml4LCBleE1hdHJpeCwgWyBmb250U2NhbGUsIGZvbnRTY2FsZSwgMSBdKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBob3cgbXVjaCBsb25nZXIgdGhlIHJlYWwgd29ybGQgZGlzdGFuY2UgaXMgYXQgdGhlIHRvcCBvZiB0aGUgc2NyZWVuXG4gICAgLy8gdGhhbiBhdCB0aGUgbWlkZGxlIG9mIHRoZSBzY3JlZW4uXG4gICAgdmFyIHRvcGVkZ2VsZW5ndGggPSBNYXRoLnNxcnQodHIuaGVpZ2h0ICogdHIuaGVpZ2h0IC8gNCAgKiAoMSArIHRyLmFsdGl0dWRlICogdHIuYWx0aXR1ZGUpKTtcbiAgICB2YXIgeCA9IHRyLmhlaWdodCAvIDIgKiBNYXRoLnRhbih0ci5fcGl0Y2gpO1xuICAgIHZhciBleHRyYSA9ICh0b3BlZGdlbGVuZ3RoICsgeCkgLyB0b3BlZGdlbGVuZ3RoIC0gMTtcblxuICAgIHZhciB0ZXh0ID0gcHJlZml4ID09PSAndGV4dCc7XG4gICAgdmFyIHNoYWRlciwgdmVydGV4LCBlbGVtZW50cywgdGV4c2l6ZTtcblxuICAgIGlmICghdGV4dCAmJiAhcGFpbnRlci5zdHlsZS5zcHJpdGUubG9hZGVkKCkpXG4gICAgICAgIHJldHVybjtcblxuICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgaWYgKHNkZikge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLnNkZlNoYWRlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaGFkZXIgPSBwYWludGVyLmljb25TaGFkZXI7XG4gICAgfVxuXG4gICAgaWYgKHRleHQpIHtcbiAgICAgICAgcGFpbnRlci5nbHlwaEF0bGFzLnVwZGF0ZVRleHR1cmUoZ2wpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgIGVsZW1lbnRzID0gdGlsZS5idWZmZXJzLmdseXBoRWxlbWVudDtcbiAgICAgICAgdGV4c2l6ZSA9IFtwYWludGVyLmdseXBoQXRsYXMud2lkdGggLyA0LCBwYWludGVyLmdseXBoQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcGFpbnRlci5zcHJpdGVBdGxhcy5iaW5kKGdsLCBhbGlnbmVkV2l0aE1hcCB8fCBwYWludGVyLm9wdGlvbnMucm90YXRpbmcgfHxcbiAgICAgICAgICAgIHBhaW50ZXIub3B0aW9ucy56b29taW5nIHx8IGZvbnRTY2FsZSAhPT0gMSB8fCBzZGYgfHwgcGFpbnRlci50cmFuc2Zvcm0ucGl0Y2gpO1xuICAgICAgICB2ZXJ0ZXggPSB0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgZWxlbWVudHMgPSB0aWxlLmJ1ZmZlcnMuaWNvbkVsZW1lbnQ7XG4gICAgICAgIHRleHNpemUgPSBbcGFpbnRlci5zcHJpdGVBdGxhcy53aWR0aCAvIDQsIHBhaW50ZXIuc3ByaXRlQXRsYXMuaGVpZ2h0IC8gNF07XG4gICAgfVxuXG4gICAgZ2wuc3dpdGNoU2hhZGVyKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3RleHR1cmUsIDApO1xuICAgIGdsLnVuaWZvcm0yZnYoc2hhZGVyLnVfdGV4c2l6ZSwgdGV4c2l6ZSk7XG4gICAgZ2wudW5pZm9ybTFpKHNoYWRlci51X3NrZXdlZCwgc2tld2VkKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfZXh0cmEsIGV4dHJhKTtcblxuICAgIC8vIGFkanVzdCBtaW4vbWF4IHpvb21zIGZvciB2YXJpYWJsZSBmb250IHNpZXNcbiAgICB2YXIgem9vbUFkanVzdCA9IE1hdGgubG9nKGZvbnRTaXplIC8gbGF5ZXIubGF5b3V0W3ByZWZpeCArICctbWF4LXNpemUnXSkgLyBNYXRoLkxOMiB8fCAwO1xuXG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X3pvb20sIChwYWludGVyLnRyYW5zZm9ybS56b29tIC0gem9vbUFkanVzdCkgKiAxMCk7IC8vIGN1cnJlbnQgem9vbSBsZXZlbFxuXG4gICAgdmFyIGYgPSBwYWludGVyLmZyYW1lSGlzdG9yeS5nZXRGYWRlUHJvcGVydGllcygzMDApO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlZGlzdCwgZi5mYWRlZGlzdCAqIDEwKTtcbiAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfbWluZmFkZXpvb20sIE1hdGguZmxvb3IoZi5taW5mYWRlem9vbSAqIDEwKSk7XG4gICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X21heGZhZGV6b29tLCBNYXRoLmZsb29yKGYubWF4ZmFkZXpvb20gKiAxMCkpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9mYWRlem9vbSwgKHBhaW50ZXIudHJhbnNmb3JtLnpvb20gKyBmLmJ1bXApICogMTApO1xuXG4gICAgdmFyIGdyb3VwLCBvZmZzZXQsIGNvdW50LCBlbGVtZW50T2Zmc2V0O1xuXG4gICAgZWxlbWVudHMuYmluZChnbCk7XG5cbiAgICBpZiAoc2RmKSB7XG4gICAgICAgIHZhciBzZGZQeCA9IDg7XG4gICAgICAgIHZhciBibHVyT2Zmc2V0ID0gMS4xOTtcbiAgICAgICAgdmFyIGhhbG9PZmZzZXQgPSA2O1xuICAgICAgICB2YXIgZ2FtbWEgPSAwLjEwNSAqIGRlZmF1bHRTaXplc1twcmVmaXhdIC8gZm9udFNpemUgLyBicm93c2VyLmRldmljZVBpeGVsUmF0aW87XG5cbiAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCBnYW1tYSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICBnbC51bmlmb3JtNGZ2KHNoYWRlci51X2NvbG9yLCBsYXllci5wYWludFtwcmVmaXggKyAnLWNvbG9yJ10pO1xuICAgICAgICBnbC51bmlmb3JtMWYoc2hhZGVyLnVfYnVmZmVyLCAoMjU2IC0gNjQpIC8gMjU2KTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2ldO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pIHtcbiAgICAgICAgICAgIC8vIERyYXcgaGFsbyB1bmRlcm5lYXRoIHRoZSB0ZXh0LlxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2dhbW1hLCAobGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWJsdXInXSAqIGJsdXJPZmZzZXQgLyBmb250U2NhbGUgLyBzZGZQeCArIGdhbW1hKSAqIGdhbW1hU2NhbGUpO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTRmdihzaGFkZXIudV9jb2xvciwgbGF5ZXIucGFpbnRbcHJlZml4ICsgJy1oYWxvLWNvbG9yJ10pO1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKHNoYWRlci51X2J1ZmZlciwgKGhhbG9PZmZzZXQgLSBsYXllci5wYWludFtwcmVmaXggKyAnLWhhbG8td2lkdGgnXSAvIGZvbnRTY2FsZSkgLyBzZGZQeCk7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgZWxlbWVudEdyb3Vwcy5ncm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2pdO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGdyb3VwLnZlcnRleFN0YXJ0SW5kZXggKiB2ZXJ0ZXguaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgdmVydGV4LmJpbmQoZ2wsIHNoYWRlciwgb2Zmc2V0KTtcblxuICAgICAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICAgICAgZWxlbWVudE9mZnNldCA9IGdyb3VwLmVsZW1lbnRTdGFydEluZGV4ICogZWxlbWVudHMuaXRlbVNpemU7XG4gICAgICAgICAgICAgICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgY291bnQsIGdsLlVOU0lHTkVEX1NIT1JULCBlbGVtZW50T2Zmc2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLnVuaWZvcm0xZihzaGFkZXIudV9vcGFjaXR5LCBsYXllci5wYWludFsnaWNvbi1vcGFjaXR5J10pO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGVsZW1lbnRHcm91cHMuZ3JvdXBzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICBncm91cCA9IGVsZW1lbnRHcm91cHMuZ3JvdXBzW2tdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleCAqIHZlcnRleC5pdGVtU2l6ZTtcbiAgICAgICAgICAgIHZlcnRleC5iaW5kKGdsLCBzaGFkZXIsIG9mZnNldCk7XG5cbiAgICAgICAgICAgIGNvdW50ID0gZ3JvdXAuZWxlbWVudExlbmd0aCAqIDM7XG4gICAgICAgICAgICBlbGVtZW50T2Zmc2V0ID0gZ3JvdXAuZWxlbWVudFN0YXJ0SW5kZXggKiBlbGVtZW50cy5pdGVtU2l6ZTtcbiAgICAgICAgICAgIGdsLmRyYXdFbGVtZW50cyhnbC5UUklBTkdMRVMsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgZWxlbWVudE9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgbWF0NCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpLm1hdDQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhd1ZlcnRpY2VzO1xuXG5mdW5jdGlvbiBkcmF3VmVydGljZXMocGFpbnRlciwgbGF5ZXIsIHBvc01hdHJpeCwgdGlsZSkge1xuICAgIHZhciBnbCA9IHBhaW50ZXIuZ2w7XG5cbiAgICBpZiAoIXRpbGUgfHwgIXRpbGUuYnVmZmVycykgcmV0dXJuO1xuICAgIHZhciBlbGVtZW50R3JvdXBzID0gdGlsZS5lbGVtZW50R3JvdXBzW2xheWVyLnJlZiB8fCBsYXllci5pZF07XG4gICAgaWYgKCFlbGVtZW50R3JvdXBzKSByZXR1cm47XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcblxuICAgIC8vIERyYXcgYWxsIGJ1ZmZlcnNcbiAgICBpZiAobGF5ZXIudHlwZSA9PT0gJ2ZpbGwnKSB7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmZpbGxWZXJ0ZXgsIGVsZW1lbnRHcm91cHMuZ3JvdXBzLCBwb3NNYXRyaXgsIDQpO1xuICAgIH0gZWxzZSBpZiAobGF5ZXIudHlwZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMuaWNvblZlcnRleCwgZWxlbWVudEdyb3Vwcy5pY29uLmdyb3VwcywgcG9zTWF0cml4LCAxNik7XG4gICAgICAgIGRyYXdQb2ludHModGlsZS5idWZmZXJzLmdseXBoVmVydGV4LCBlbGVtZW50R3JvdXBzLnRleHQuZ3JvdXBzLCBwb3NNYXRyaXgsIDE2KTtcbiAgICB9IGVsc2UgaWYgKGxheWVyLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgICB2YXIgbmV3UG9zTWF0cml4ID0gbWF0NC5jbG9uZShwb3NNYXRyaXgpO1xuICAgICAgICBtYXQ0LnNjYWxlKG5ld1Bvc01hdHJpeCwgbmV3UG9zTWF0cml4LCBbMC41LCAwLjUsIDFdKTtcbiAgICAgICAgZHJhd1BvaW50cyh0aWxlLmJ1ZmZlcnMubGluZVZlcnRleCwgZWxlbWVudEdyb3Vwcy5ncm91cHMsIG5ld1Bvc01hdHJpeCwgOCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1BvaW50cyh2ZXJ0ZXgsIGdyb3VwcywgbWF0cml4LCBzdHJpZGUpIHtcbiAgICAgICAgZ2wuc3dpdGNoU2hhZGVyKHBhaW50ZXIuZG90U2hhZGVyLCBtYXRyaXgpO1xuXG4gICAgICAgIGdsLnVuaWZvcm0xZihwYWludGVyLmRvdFNoYWRlci51X3NpemUsIDQgKiBicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICBnbC51bmlmb3JtMWYocGFpbnRlci5kb3RTaGFkZXIudV9ibHVyLCAwLjI1KTtcbiAgICAgICAgZ2wudW5pZm9ybTRmdihwYWludGVyLmRvdFNoYWRlci51X2NvbG9yLCBbMC4xLCAwLCAwLCAwLjFdKTtcblxuICAgICAgICB2ZXJ0ZXguYmluZChnbCwgcGFpbnRlci5kb3RTaGFkZXIsIDApO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldO1xuICAgICAgICAgICAgdmFyIGJlZ2luID0gZ3JvdXAudmVydGV4U3RhcnRJbmRleDtcbiAgICAgICAgICAgIHZhciBjb3VudCA9IGdyb3VwLnZlcnRleExlbmd0aDtcbiAgICAgICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIocGFpbnRlci5kb3RTaGFkZXIuYV9wb3MsIDIsIGdsLlNIT1JULCBmYWxzZSwgc3RyaWRlLCAwKTtcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCBiZWdpbiwgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gRnJhbWVIaXN0b3J5O1xuXG5mdW5jdGlvbiBGcmFtZUhpc3RvcnkoKSB7XG4gICAgdGhpcy5mcmFtZUhpc3RvcnkgPSBbXTtcbn1cblxuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5nZXRGYWRlUHJvcGVydGllcyA9IGZ1bmN0aW9uKGR1cmF0aW9uKSB7XG4gICAgaWYgKGR1cmF0aW9uID09PSB1bmRlZmluZWQpIGR1cmF0aW9uID0gMzAwO1xuICAgIHZhciBjdXJyZW50VGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG5cbiAgICAvLyBSZW1vdmUgZnJhbWVzIHVudGlsIG9ubHkgb25lIGlzIG91dHNpZGUgdGhlIGR1cmF0aW9uLCBvciB1bnRpbCB0aGVyZSBhcmUgb25seSB0aHJlZVxuICAgIHdoaWxlICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPiAzICYmIHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5LnNoaWZ0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZnJhbWVIaXN0b3J5WzFdLnRpbWUgKyBkdXJhdGlvbiA8IGN1cnJlbnRUaW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWVIaXN0b3J5WzBdLnogPSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56O1xuICAgIH1cblxuICAgIHZhciBmcmFtZUxlbiA9IHRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aDtcbiAgICBpZiAoZnJhbWVMZW4gPCAzKSBjb25zb2xlLndhcm4oJ3RoZXJlIHNob3VsZCBuZXZlciBiZSBsZXNzIHRoYW4gdGhyZWUgZnJhbWVzIGluIHRoZSBoaXN0b3J5Jyk7XG5cbiAgICAvLyBGaW5kIHRoZSByYW5nZSBvZiB6b29tIGxldmVscyB3ZSB3YW50IHRvIGZhZGUgYmV0d2VlblxuICAgIHZhciBzdGFydGluZ1ogPSB0aGlzLmZyYW1lSGlzdG9yeVswXS56LFxuICAgICAgICBsYXN0RnJhbWUgPSB0aGlzLmZyYW1lSGlzdG9yeVtmcmFtZUxlbiAtIDFdLFxuICAgICAgICBlbmRpbmdaID0gbGFzdEZyYW1lLnosXG4gICAgICAgIGxvd1ogPSBNYXRoLm1pbihzdGFydGluZ1osIGVuZGluZ1opLFxuICAgICAgICBoaWdoWiA9IE1hdGgubWF4KHN0YXJ0aW5nWiwgZW5kaW5nWik7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHNwZWVkIG9mIHpvb21pbmcsIGFuZCBob3cgZmFyIGl0IHdvdWxkIHpvb20gaW4gdGVybXMgb2Ygem9vbSBsZXZlbHMgaW4gb25lIGR1cmF0aW9uXG4gICAgdmFyIHpvb21EaWZmID0gbGFzdEZyYW1lLnogLSB0aGlzLmZyYW1lSGlzdG9yeVsxXS56LFxuICAgICAgICB0aW1lRGlmZiA9IGxhc3RGcmFtZS50aW1lIC0gdGhpcy5mcmFtZUhpc3RvcnlbMV0udGltZTtcbiAgICB2YXIgZmFkZWRpc3QgPSB6b29tRGlmZiAvICh0aW1lRGlmZiAvIGR1cmF0aW9uKTtcblxuICAgIGlmIChpc05hTihmYWRlZGlzdCkpIGNvbnNvbGUud2FybignZmFkZWRpc3Qgc2hvdWxkIG5ldmVyIGJlIE5hTicpO1xuXG4gICAgLy8gQXQgZW5kIG9mIGEgem9vbSB3aGVuIHRoZSB6b29tIHN0b3BzIGNoYW5naW5nIGNvbnRpbnVlIHByZXRlbmRpbmcgdG8gem9vbSBhdCB0aGF0IHNwZWVkXG4gICAgLy8gYnVtcCBpcyBob3cgbXVjaCBmYXJ0aGVyIGl0IHdvdWxkIGhhdmUgYmVlbiBpZiBpdCBoYWQgY29udGludWVkIHpvb21pbmcgYXQgdGhlIHNhbWUgcmF0ZVxuICAgIHZhciBidW1wID0gKGN1cnJlbnRUaW1lIC0gbGFzdEZyYW1lLnRpbWUpIC8gZHVyYXRpb24gKiBmYWRlZGlzdDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZhZGVkaXN0OiBmYWRlZGlzdCxcbiAgICAgICAgbWluZmFkZXpvb206IGxvd1osXG4gICAgICAgIG1heGZhZGV6b29tOiBoaWdoWixcbiAgICAgICAgYnVtcDogYnVtcFxuICAgIH07XG59O1xuXG4vLyBSZWNvcmQgZnJhbWUgaGlzdG9yeSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYWxjdWxhdGUgZmFkaW5nIHBhcmFtc1xuRnJhbWVIaXN0b3J5LnByb3RvdHlwZS5yZWNvcmQgPSBmdW5jdGlvbih6b29tKSB7XG4gICAgdmFyIGN1cnJlbnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuICAgIC8vIGZpcnN0IGZyYW1lIGV2ZXJcbiAgICBpZiAoIXRoaXMuZnJhbWVIaXN0b3J5Lmxlbmd0aCkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHt0aW1lOiAwLCB6OiB6b29tIH0sIHt0aW1lOiAwLCB6OiB6b29tIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZyYW1lSGlzdG9yeS5sZW5ndGggPT09IDIgfHwgdGhpcy5mcmFtZUhpc3RvcnlbdGhpcy5mcmFtZUhpc3RvcnkubGVuZ3RoIC0gMV0ueiAhPT0gem9vbSkge1xuICAgICAgICB0aGlzLmZyYW1lSGlzdG9yeS5wdXNoKHtcbiAgICAgICAgICAgIHRpbWU6IGN1cnJlbnRUaW1lLFxuICAgICAgICAgICAgejogem9vbVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hhZGVycyA9IHJlcXVpcmUoJy4vc2hhZGVycycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxuZXhwb3J0cy5leHRlbmQgPSBmdW5jdGlvbihjb250ZXh0KSB7XG4gICAgdmFyIG9yaWdMaW5lV2lkdGggPSBjb250ZXh0LmxpbmVXaWR0aCxcbiAgICAgICAgbGluZVdpZHRoUmFuZ2UgPSBjb250ZXh0LmdldFBhcmFtZXRlcihjb250ZXh0LkFMSUFTRURfTElORV9XSURUSF9SQU5HRSk7XG5cbiAgICBjb250ZXh0LmxpbmVXaWR0aCA9IGZ1bmN0aW9uKHdpZHRoKSB7XG4gICAgICAgIG9yaWdMaW5lV2lkdGguY2FsbChjb250ZXh0LCB1dGlsLmNsYW1wKHdpZHRoLCBsaW5lV2lkdGhSYW5nZVswXSwgbGluZVdpZHRoUmFuZ2VbMV0pKTtcbiAgICB9O1xuXG4gICAgY29udGV4dC5nZXRTaGFkZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlKSB7XG4gICAgICAgIHZhciBraW5kID0gdHlwZSA9PT0gdGhpcy5GUkFHTUVOVF9TSEFERVIgPyAnZnJhZ21lbnQnIDogJ3ZlcnRleCc7XG4gICAgICAgIGlmICghc2hhZGVyc1tuYW1lXSB8fCAhc2hhZGVyc1tuYW1lXVtraW5kXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgc2hhZGVyIFwiICsgbmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hhZGVyID0gdGhpcy5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgIHRoaXMuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyc1tuYW1lXVtraW5kXSk7XG4gICAgICAgIHRoaXMuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICBpZiAoIXRoaXMuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgdGhpcy5DT01QSUxFX1NUQVRVUykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNoYWRlcjtcbiAgICB9O1xuXG4gICAgY29udGV4dC5pbml0aWFsaXplU2hhZGVyID0gZnVuY3Rpb24obmFtZSwgYXR0cmlidXRlcywgdW5pZm9ybXMpIHtcbiAgICAgICAgdmFyIHNoYWRlciA9IHtcbiAgICAgICAgICAgIHByb2dyYW06IHRoaXMuY3JlYXRlUHJvZ3JhbSgpLFxuICAgICAgICAgICAgZnJhZ21lbnQ6IHRoaXMuZ2V0U2hhZGVyKG5hbWUsIHRoaXMuRlJBR01FTlRfU0hBREVSKSxcbiAgICAgICAgICAgIHZlcnRleDogdGhpcy5nZXRTaGFkZXIobmFtZSwgdGhpcy5WRVJURVhfU0hBREVSKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYXR0YWNoU2hhZGVyKHNoYWRlci5wcm9ncmFtLCBzaGFkZXIudmVydGV4KTtcbiAgICAgICAgdGhpcy5hdHRhY2hTaGFkZXIoc2hhZGVyLnByb2dyYW0sIHNoYWRlci5mcmFnbWVudCk7XG4gICAgICAgIHRoaXMubGlua1Byb2dyYW0oc2hhZGVyLnByb2dyYW0pO1xuXG4gICAgICAgIGlmICghdGhpcy5nZXRQcm9ncmFtUGFyYW1ldGVyKHNoYWRlci5wcm9ncmFtLCB0aGlzLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLmdldFByb2dyYW1JbmZvTG9nKHNoYWRlci5wcm9ncmFtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaGFkZXJbYXR0cmlidXRlc1tpXV0gPSB0aGlzLmdldEF0dHJpYkxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCBhdHRyaWJ1dGVzW2ldKTtcbiAgICAgICAgICAgICAgICBzaGFkZXIuYXR0cmlidXRlcy5wdXNoKHNoYWRlclthdHRyaWJ1dGVzW2ldXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHVuaWZvcm1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgc2hhZGVyW3VuaWZvcm1zW2tdXSA9IHRoaXMuZ2V0VW5pZm9ybUxvY2F0aW9uKHNoYWRlci5wcm9ncmFtLCB1bmlmb3Jtc1trXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH07XG5cbiAgICAvLyBTd2l0Y2hlcyB0byBhIGRpZmZlcmVudCBzaGFkZXIgcHJvZ3JhbS5cbiAgICBjb250ZXh0LnN3aXRjaFNoYWRlciA9IGZ1bmN0aW9uKHNoYWRlciwgcG9zTWF0cml4LCBleE1hdHJpeCkge1xuICAgICAgICBpZiAoIXBvc01hdHJpeCkge1xuICAgICAgICAgICAgY29uc29sZS50cmFjZSgncG9zTWF0cml4IGRvZXMgbm90IGhhdmUgcmVxdWlyZWQgYXJndW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTaGFkZXIgIT09IHNoYWRlcikge1xuICAgICAgICAgICAgdGhpcy51c2VQcm9ncmFtKHNoYWRlci5wcm9ncmFtKTtcblxuICAgICAgICAgICAgLy8gRGlzYWJsZSBhbGwgYXR0cmlidXRlcyBmcm9tIHRoZSBleGlzdGluZyBzaGFkZXIgdGhhdCBhcmVuJ3QgdXNlZCBpblxuICAgICAgICAgICAgLy8gdGhlIG5ldyBzaGFkZXIuIE5vdGU6IGF0dHJpYnV0ZSBpbmRpY2VzIGFyZSAqbm90KiBwcm9ncmFtIHNwZWNpZmljIVxuICAgICAgICAgICAgdmFyIGVuYWJsZWQgPSB0aGlzLmN1cnJlbnRTaGFkZXIgPyB0aGlzLmN1cnJlbnRTaGFkZXIuYXR0cmlidXRlcyA6IFtdO1xuICAgICAgICAgICAgdmFyIHJlcXVpcmVkID0gc2hhZGVyLmF0dHJpYnV0ZXM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW5hYmxlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlZC5pbmRleE9mKGVuYWJsZWRbaV0pIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShlbmFibGVkW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVuYWJsZSBhbGwgYXR0cmlidXRlcyBmb3IgdGhlIG5ldyBzaGFkZXIuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlcXVpcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVuYWJsZWQuaW5kZXhPZihyZXF1aXJlZFtqXSkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkocmVxdWlyZWRbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U2hhZGVyID0gc2hhZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtYXRyaWNlcyBpZiBuZWNlc3NhcnkuIE5vdGU6IFRoaXMgcmVsaWVzIG9uIG9iamVjdCBpZGVudGl0eSFcbiAgICAgICAgLy8gVGhpcyBtZWFucyBjaGFuZ2luZyB0aGUgbWF0cml4IHZhbHVlcyB3aXRob3V0IHRoZSBhY3R1YWwgbWF0cml4IG9iamVjdFxuICAgICAgICAvLyB3aWxsIEZBSUwgdG8gdXBkYXRlIHRoZSBtYXRyaXggcHJvcGVybHkuXG4gICAgICAgIGlmIChzaGFkZXIucG9zTWF0cml4ICE9PSBwb3NNYXRyaXgpIHtcbiAgICAgICAgICAgIHRoaXMudW5pZm9ybU1hdHJpeDRmdihzaGFkZXIudV9tYXRyaXgsIGZhbHNlLCBwb3NNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLnBvc01hdHJpeCA9IHBvc01hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhNYXRyaXggJiYgc2hhZGVyLmV4TWF0cml4ICE9PSBleE1hdHJpeCAmJiBzaGFkZXIudV9leG1hdHJpeCkge1xuICAgICAgICAgICAgdGhpcy51bmlmb3JtTWF0cml4NGZ2KHNoYWRlci51X2V4bWF0cml4LCBmYWxzZSwgZXhNYXRyaXgpO1xuICAgICAgICAgICAgc2hhZGVyLmV4TWF0cml4ID0gZXhNYXRyaXg7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpbmVBdGxhcztcblxuLyoqXG4gKiBNdWNoIGxpa2UgYSBHbHlwaEF0bGFzLCBhIExpbmVBdGxhcyBsZXRzIHVzIHJldXNlIHJlbmRlcmVkIGRhc2hlZCBsaW5lc1xuICogYnkgd3JpdGluZyBtYW55IG9mIHRoZW0gdG8gYSB0ZXh0dXJlIGFuZCB0aGVuIGZldGNoaW5nIHRoZWlyIHBvc2l0aW9uc1xuICogdXNpbmcgLmdldERhc2guXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBMaW5lQXRsYXMod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLm5leHRSb3cgPSAwO1xuXG4gICAgdGhpcy5ieXRlcyA9IDQ7XG4gICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy53aWR0aCAqIHRoaXMuaGVpZ2h0ICogdGhpcy5ieXRlcyk7XG5cbiAgICB0aGlzLnBvc2l0aW9ucyA9IHt9O1xufVxuXG5MaW5lQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuLyoqXG4gKiBHZXQgb3IgY3JlYXRlIGEgZGFzaCBsaW5lIHBhdHRlcm4uXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBkYXNoYXJyYXlcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gcm91bmQgd2hldGhlciB0byBhZGQgY2lyY2xlIGNhcHMgaW4gYmV0d2VlbiBkYXNoIHNlZ21lbnRzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwb3NpdGlvbiBvZiBkYXNoIHRleHR1cmUgaW4geyB5LCBoZWlnaHQsIHdpZHRoIH1cbiAqIEBwcml2YXRlXG4gKi9cbkxpbmVBdGxhcy5wcm90b3R5cGUuZ2V0RGFzaCA9IGZ1bmN0aW9uKGRhc2hhcnJheSwgcm91bmQpIHtcbiAgICB2YXIga2V5ID0gZGFzaGFycmF5LmpvaW4oXCIsXCIpICsgcm91bmQ7XG5cbiAgICBpZiAoIXRoaXMucG9zaXRpb25zW2tleV0pIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbnNba2V5XSA9IHRoaXMuYWRkRGFzaChkYXNoYXJyYXksIHJvdW5kKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucG9zaXRpb25zW2tleV07XG59O1xuXG5MaW5lQXRsYXMucHJvdG90eXBlLmFkZERhc2ggPSBmdW5jdGlvbihkYXNoYXJyYXksIHJvdW5kKSB7XG5cbiAgICB2YXIgbiA9IHJvdW5kID8gNyA6IDA7XG4gICAgdmFyIGhlaWdodCA9IDIgKiBuICsgMTtcbiAgICB2YXIgb2Zmc2V0ID0gMTI4O1xuXG4gICAgaWYgKHRoaXMubmV4dFJvdyArIGhlaWdodCA+IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTGluZUF0bGFzIG91dCBvZiBzcGFjZScpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhc2hhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZW5ndGggKz0gZGFzaGFycmF5W2ldO1xuICAgIH1cblxuICAgIHZhciBzdHJldGNoID0gdGhpcy53aWR0aCAvIGxlbmd0aDtcbiAgICB2YXIgaGFsZldpZHRoID0gc3RyZXRjaCAvIDI7XG5cbiAgICAvLyBJZiBkYXNoYXJyYXkgaGFzIGFuIG9kZCBsZW5ndGgsIGJvdGggdGhlIGZpcnN0IGFuZCBsYXN0IHBhcnRzXG4gICAgLy8gYXJlIGRhc2hlcyBhbmQgc2hvdWxkIGJlIGpvaW5lZCBzZWFtbGVzc2x5LlxuICAgIHZhciBvZGRMZW5ndGggPSBkYXNoYXJyYXkubGVuZ3RoICUgMiA9PT0gMTtcblxuICAgIGZvciAodmFyIHkgPSAtbjsgeSA8PSBuOyB5KyspIHtcbiAgICAgICAgdmFyIHJvdyA9IHRoaXMubmV4dFJvdyArIG4gKyB5O1xuICAgICAgICB2YXIgaW5kZXggPSB0aGlzLndpZHRoICogcm93O1xuXG4gICAgICAgIHZhciBsZWZ0ID0gb2RkTGVuZ3RoID8gLWRhc2hhcnJheVtkYXNoYXJyYXkubGVuZ3RoIC0gMV0gOiAwO1xuICAgICAgICB2YXIgcmlnaHQgPSBkYXNoYXJyYXlbMF07XG4gICAgICAgIHZhciBwYXJ0SW5kZXggPSAxO1xuXG4gICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgdGhpcy53aWR0aDsgeCsrKSB7XG5cbiAgICAgICAgICAgIHdoaWxlIChyaWdodCA8IHggLyBzdHJldGNoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQgKyBkYXNoYXJyYXlbcGFydEluZGV4XTtcblxuICAgICAgICAgICAgICAgIGlmIChvZGRMZW5ndGggJiYgcGFydEluZGV4ID09PSBkYXNoYXJyYXkubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICByaWdodCArPSBkYXNoYXJyYXlbMF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcGFydEluZGV4Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBkaXN0TGVmdCA9IE1hdGguYWJzKHggLSBsZWZ0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdFJpZ2h0ID0gTWF0aC5hYnMoeCAtIHJpZ2h0ICogc3RyZXRjaCk7XG4gICAgICAgICAgICB2YXIgZGlzdCA9IE1hdGgubWluKGRpc3RMZWZ0LCBkaXN0UmlnaHQpO1xuICAgICAgICAgICAgdmFyIGluc2lkZSA9IChwYXJ0SW5kZXggJSAyKSA9PT0gMTtcbiAgICAgICAgICAgIHZhciBzaWduZWREaXN0YW5jZTtcblxuICAgICAgICAgICAgaWYgKHJvdW5kKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGNpcmNsZSBjYXBzXG4gICAgICAgICAgICAgICAgdmFyIGRpc3RNaWRkbGUgPSBuID8geSAvIG4gKiAoaGFsZldpZHRoICsgMSkgOiAwO1xuICAgICAgICAgICAgICAgIGlmIChpbnNpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RFZGdlID0gaGFsZldpZHRoIC0gTWF0aC5hYnMoZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgICAgIHNpZ25lZERpc3RhbmNlID0gTWF0aC5zcXJ0KGRpc3QgKiBkaXN0ICsgZGlzdEVkZ2UgKiBkaXN0RWRnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2lnbmVkRGlzdGFuY2UgPSBoYWxmV2lkdGggLSBNYXRoLnNxcnQoZGlzdCAqIGRpc3QgKyBkaXN0TWlkZGxlICogZGlzdE1pZGRsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduZWREaXN0YW5jZSA9IChpbnNpZGUgPyAxIDogLTEpICogZGlzdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5kYXRhWzMgKyAoaW5kZXggKyB4KSAqIDRdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBzaWduZWREaXN0YW5jZSArIG9mZnNldCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHtcbiAgICAgICAgeTogKHRoaXMubmV4dFJvdyArIG4gKyAwLjUpIC8gdGhpcy5oZWlnaHQsXG4gICAgICAgIGhlaWdodDogMiAqIG4gLyB0aGlzLmhlaWdodCxcbiAgICAgICAgd2lkdGg6IGxlbmd0aFxuICAgIH07XG5cbiAgICB0aGlzLm5leHRSb3cgKz0gaGVpZ2h0O1xuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHBvcztcbn07XG5cbkxpbmVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgaWYgKCF0aGlzLnRleHR1cmUpIHtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5SRVBFQVQpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHRoaXMuZGF0YSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuXG4gICAgICAgIGlmICh0aGlzLmRpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLmRhdGEpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuTGluZUF0bGFzLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjYW52YXMpO1xuICAgIGNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgY2FudmFzLnN0eWxlLnRvcCA9IDA7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAwO1xuICAgIGNhbnZhcy5zdHlsZS5iYWNrZ3JvdW5kID0gJyNmZjAnO1xuXG4gICAgY2FudmFzLndpZHRoID0gdGhpcy53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdmFyIGRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5zZGYpIHtcbiAgICAgICAgICAgIHZhciBrID0gaSAqIDQ7XG4gICAgICAgICAgICBkYXRhLmRhdGFba10gPSBkYXRhLmRhdGFbayArIDFdID0gZGF0YS5kYXRhW2sgKyAyXSA9IDA7XG4gICAgICAgICAgICBkYXRhLmRhdGFbayArIDNdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0YS5kYXRhW2ldID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIGN0eC5wdXRJbWFnZURhdGEoZGF0YSwgMCwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2x1dGlsID0gcmVxdWlyZSgnLi9nbF91dGlsJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIG1hdDQgPSByZXF1aXJlKCdnbC1tYXRyaXgnKS5tYXQ0O1xudmFyIEZyYW1lSGlzdG9yeSA9IHJlcXVpcmUoJy4vZnJhbWVfaGlzdG9yeScpO1xuXG4vKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBwYWludGVyIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0NhbnZhc30gZ2wgYW4gZXhwZXJpbWVudGFsLXdlYmdsIGRyYXdpbmcgY29udGV4dFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IFBhaW50ZXI7XG5mdW5jdGlvbiBQYWludGVyKGdsLCB0cmFuc2Zvcm0pIHtcbiAgICB0aGlzLmdsID0gZ2x1dGlsLmV4dGVuZChnbCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5cbiAgICB0aGlzLnJldXNhYmxlVGV4dHVyZXMgPSB7fTtcbiAgICB0aGlzLnByZUZib3MgPSB7fTtcblxuICAgIHRoaXMuZnJhbWVIaXN0b3J5ID0gbmV3IEZyYW1lSGlzdG9yeSgpO1xuXG4gICAgdGhpcy5zZXR1cCgpO1xufVxuXG4vKlxuICogVXBkYXRlIHRoZSBHTCB2aWV3cG9ydCwgcHJvamVjdGlvbiBtYXRyaXgsIGFuZCB0cmFuc2Zvcm1zIHRvIGNvbXBlbnNhdGVcbiAqIGZvciBhIG5ldyB3aWR0aCBhbmQgaGVpZ2h0IHZhbHVlLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcblxuICAgIHRoaXMud2lkdGggPSB3aWR0aCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodCAqIGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICBnbC52aWV3cG9ydCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cbn07XG5cblxuUGFpbnRlci5wcm90b3R5cGUuc2V0dXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgZ2wudmVyYm9zZSA9IHRydWU7XG5cbiAgICAvLyBXZSBhcmUgYmxlbmRpbmcgdGhlIG5ldyBwaXhlbHMgKmJlaGluZCogdGhlIGV4aXN0aW5nIHBpeGVscy4gVGhhdCB3YXkgd2UgY2FuXG4gICAgLy8gZHJhdyBmcm9udC10by1iYWNrIGFuZCB1c2UgdGhlbiBzdGVuY2lsIGJ1ZmZlciB0byBjdWxsIG9wYXF1ZSBwaXhlbHMgZWFybHkuXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKTtcbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FX01JTlVTX0RTVF9BTFBIQSwgZ2wuT05FKTtcblxuICAgIGdsLmVuYWJsZShnbC5TVEVOQ0lMX1RFU1QpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaGFkZXJzXG4gICAgdGhpcy5kZWJ1Z1NoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2RlYnVnJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfcG9pbnRzaXplJywgJ3VfY29sb3InXSk7XG5cbiAgICB0aGlzLmdhdXNzaWFuU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZ2F1c3NpYW4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9pbWFnZScsICd1X29mZnNldCddKTtcblxuICAgIHRoaXMucmFzdGVyU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcigncmFzdGVyJyxcbiAgICAgICAgWydhX3BvcycsICdhX3RleHR1cmVfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9icmlnaHRuZXNzX2xvdycsICd1X2JyaWdodG5lc3NfaGlnaCcsICd1X3NhdHVyYXRpb25fZmFjdG9yJywgJ3Vfc3Bpbl93ZWlnaHRzJywgJ3VfY29udHJhc3RfZmFjdG9yJywgJ3Vfb3BhY2l0eTAnLCAndV9vcGFjaXR5MScsICd1X2ltYWdlMCcsICd1X2ltYWdlMScsICd1X3RsX3BhcmVudCcsICd1X3NjYWxlX3BhcmVudCcsICd1X2J1ZmZlcl9zY2FsZSddKTtcblxuICAgIHRoaXMubGluZVNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2xpbmUnLFxuICAgICAgICBbJ2FfcG9zJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfbGluZXdpZHRoJywgJ3VfY29sb3InLCAndV9yYXRpbycsICd1X2JsdXInLCAndV9leHRyYScsICd1X2FudGlhbGlhc2luZ21hdHJpeCddKTtcblxuICAgIHRoaXMubGluZXBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X3JhdGlvJywgJ3VfcGF0dGVybl9zaXplX2EnLCAndV9wYXR0ZXJuX3NpemVfYicsICd1X3BhdHRlcm5fdGxfYScsICd1X3BhdHRlcm5fYnJfYScsICd1X3BhdHRlcm5fdGxfYicsICd1X3BhdHRlcm5fYnJfYicsICd1X2JsdXInLCAndV9mYWRlJywgJ3Vfb3BhY2l0eSddKTtcblxuICAgIHRoaXMubGluZXNkZnBhdHRlcm5TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdsaW5lc2RmcGF0dGVybicsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9kYXRhJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9leG1hdHJpeCcsICd1X2xpbmV3aWR0aCcsICd1X2NvbG9yJywgJ3VfcmF0aW8nLCAndV9ibHVyJywgJ3VfcGF0dGVybnNjYWxlX2EnLCAndV90ZXhfeV9hJywgJ3VfcGF0dGVybnNjYWxlX2InLCAndV90ZXhfeV9iJywgJ3VfaW1hZ2UnLCAndV9zZGZnYW1tYScsICd1X21peCddKTtcblxuICAgIHRoaXMuZG90U2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignZG90JyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2l6ZScsICd1X2NvbG9yJywgJ3VfYmx1ciddKTtcblxuICAgIHRoaXMuc2RmU2hhZGVyID0gZ2wuaW5pdGlhbGl6ZVNoYWRlcignc2RmJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV9jb2xvcicsICd1X2dhbW1hJywgJ3VfYnVmZmVyJywgJ3Vfem9vbScsICd1X2ZhZGVkaXN0JywgJ3VfbWluZmFkZXpvb20nLCAndV9tYXhmYWRlem9vbScsICd1X2ZhZGV6b29tJywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLmljb25TaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdpY29uJyxcbiAgICAgICAgWydhX3BvcycsICdhX29mZnNldCcsICdhX2RhdGExJywgJ2FfZGF0YTInXSxcbiAgICAgICAgWyd1X21hdHJpeCcsICd1X2V4bWF0cml4JywgJ3VfdGV4dHVyZScsICd1X3RleHNpemUnLCAndV96b29tJywgJ3VfZmFkZWRpc3QnLCAndV9taW5mYWRlem9vbScsICd1X21heGZhZGV6b29tJywgJ3VfZmFkZXpvb20nLCAndV9vcGFjaXR5JywgJ3Vfc2tld2VkJywgJ3VfZXh0cmEnXSk7XG5cbiAgICB0aGlzLm91dGxpbmVTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdvdXRsaW5lJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InLCAndV93b3JsZCddXG4gICAgKTtcblxuICAgIHRoaXMucGF0dGVyblNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ3BhdHRlcm4nLFxuICAgICAgICBbJ2FfcG9zJ10sXG4gICAgICAgIFsndV9tYXRyaXgnLCAndV9wYXR0ZXJuX3RsX2EnLCAndV9wYXR0ZXJuX2JyX2EnLCAndV9wYXR0ZXJuX3RsX2InLCAndV9wYXR0ZXJuX2JyX2InLCAndV9taXgnLCAndV9wYXR0ZXJubWF0cml4X2EnLCAndV9wYXR0ZXJubWF0cml4X2InLCAndV9vcGFjaXR5JywgJ3VfaW1hZ2UnXVxuICAgICk7XG5cbiAgICB0aGlzLmZpbGxTaGFkZXIgPSBnbC5pbml0aWFsaXplU2hhZGVyKCdmaWxsJyxcbiAgICAgICAgWydhX3BvcyddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3VfY29sb3InXVxuICAgICk7XG5cbiAgICB0aGlzLmNvbGxpc2lvbkJveFNoYWRlciA9IGdsLmluaXRpYWxpemVTaGFkZXIoJ2NvbGxpc2lvbmJveCcsXG4gICAgICAgIFsnYV9wb3MnLCAnYV9leHRydWRlJywgJ2FfZGF0YSddLFxuICAgICAgICBbJ3VfbWF0cml4JywgJ3Vfc2NhbGUnLCAndV96b29tJywgJ3VfbWF4em9vbSddXG4gICAgKTtcblxuICAgIHRoaXMuaWRlbnRpdHlNYXRyaXggPSBtYXQ0LmNyZWF0ZSgpO1xuXG4gICAgLy8gVGhlIGJhY2tncm91bmRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gdGhlIGZ1bGwgKmNhbnZhcypcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUgPSAyO1xuICAgIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQgPSA0O1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCBuZXcgSW50MTZBcnJheShbLTEsIC0xLCAxLCAtMSwgLTEsIDEsIDEsIDFdKSwgZ2wuU1RBVElDX0RSQVcpO1xuXG4gICAgdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG5cbiAgICAvLyBUaGUgZGVidWdUZXh0QnVmZmVyIGlzIHVzZWQgdG8gZHJhdyB0aWxlIElEcyBmb3IgZGVidWdnaW5nXG4gICAgdGhpcy5kZWJ1Z1RleHRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnVGV4dEJ1ZmZlci5pdGVtU2l6ZSA9IDI7XG59O1xuXG4vKipcbiAqIFJlYmluZCB0aGUgbmVjZXNzYXJ5IGJ1ZmZlcnMgdG8gcmVuZGVyIGF0IGEgZGlmZmVyZW50IGV4dGVudCB0aGFuXG4gKiB0aGUgY3VycmVudCBvbmUuIE5vLW9wcyBpZiB0aGUgZXh0ZW50IGlzIG5vdCBjaGFuZ2luZy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbmV3RXh0ZW50XG4gKiBAZXhhbXBsZVxuICogdGhpcy5zZXRFeHRlbnQoNDA5Nik7XG4gKi9cblBhaW50ZXIucHJvdG90eXBlLnNldEV4dGVudCA9IGZ1bmN0aW9uKG5ld0V4dGVudCkge1xuICAgIGlmICghbmV3RXh0ZW50IHx8IG5ld0V4dGVudCA9PT0gdGhpcy50aWxlRXh0ZW50KSByZXR1cm47XG5cbiAgICB0aGlzLnRpbGVFeHRlbnQgPSBuZXdFeHRlbnQ7XG5cbiAgICB2YXIgZ2wgPSB0aGlzLmdsO1xuXG4gICAgLy8gVGhlIHRpbGVFeHRlbnRCdWZmZXIgaXMgdXNlZCB3aGVuIGRyYXdpbmcgdG8gYSBmdWxsICp0aWxlKlxuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgIHRoaXMudGlsZUV4dGVudEJ1ZmZlci5pdGVtU2l6ZSA9IDQ7XG4gICAgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCA9IDQ7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudGlsZUV4dGVudEJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShcbiAgICAgICAgZ2wuQVJSQVlfQlVGRkVSLFxuICAgICAgICBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICAvLyB0aWxlIGNvb3JkIHgsIHRpbGUgY29vcmQgeSwgdGV4dHVyZSBjb29yZCB4LCB0ZXh0dXJlIGNvb3JkIHlcbiAgICAgICAgICAgIDAsIDAsIDAsIDAsXG4gICAgICAgICAgICB0aGlzLnRpbGVFeHRlbnQsIDAsIDMyNzY3LCAwLFxuICAgICAgICAgICAgMCwgdGhpcy50aWxlRXh0ZW50LCAwLCAzMjc2NyxcbiAgICAgICAgICAgIHRoaXMudGlsZUV4dGVudCwgdGhpcy50aWxlRXh0ZW50LCAgMzI3NjcsIDMyNzY3XG4gICAgICAgIF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAvLyBUaGUgZGVidWdCdWZmZXIgaXMgdXNlZCB0byBkcmF3IHRpbGUgb3V0bGluZXMgZm9yIGRlYnVnZ2luZ1xuICAgIHRoaXMuZGVidWdCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1TaXplID0gMjtcbiAgICB0aGlzLmRlYnVnQnVmZmVyLml0ZW1Db3VudCA9IDU7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMuZGVidWdCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoXG4gICAgICAgIGdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgbmV3IEludDE2QXJyYXkoW1xuICAgICAgICAgICAgMCwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgdGhpcy50aWxlRXh0ZW50IC0gMSwgMCwgMF0pLFxuICAgICAgICBnbC5TVEFUSUNfRFJBVyk7XG59O1xuXG4vKlxuICogUmVzZXQgdGhlIGNvbG9yIGJ1ZmZlcnMgb2YgdGhlIGRyYXdpbmcgY2FudmFzLlxuICovXG5QYWludGVyLnByb3RvdHlwZS5jbGVhckNvbG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5jbGVhckNvbG9yKDAsIDAsIDAsIDApO1xuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpO1xufTtcblxuLypcbiAqIFJlc2V0IHRoZSBkcmF3aW5nIGNhbnZhcyBieSBjbGVhcmluZyB0aGUgc3RlbmNpbCBidWZmZXIgc28gdGhhdCB3ZSBjYW4gZHJhd1xuICogbmV3IHRpbGVzIGF0IHRoZSBzYW1lIGxvY2F0aW9uLCB3aGlsZSByZXRhaW5pbmcgcHJldmlvdXNseSBkcmF3biBwaXhlbHMuXG4gKi9cblBhaW50ZXIucHJvdG90eXBlLmNsZWFyU3RlbmNpbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhGRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdDbGlwcGluZ01hc2sgPSBmdW5jdGlvbih0aWxlKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5zd2l0Y2hTaGFkZXIodGhpcy5maWxsU2hhZGVyLCB0aWxlLnBvc01hdHJpeCk7XG4gICAgZ2wuY29sb3JNYXNrKGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcblxuICAgIC8vIENsZWFyIHRoZSBlbnRpcmUgc3RlbmNpbCBidWZmZXIsIGV4Y2VwdCBmb3IgdGhlIDd0aCBiaXQsIHdoaWNoIHN0b3Jlc1xuICAgIC8vIHRoZSBnbG9iYWwgY2xpcHBpbmcgbWFzayB0aGF0IGFsbG93cyB1cyB0byBhdm9pZCBkcmF3aW5nIGluIHJlZ2lvbnMgb2ZcbiAgICAvLyB0aWxlcyB3ZSd2ZSBhbHJlYWR5IHBhaW50ZWQgaW4uXG4gICAgZ2wuY2xlYXJTdGVuY2lsKDB4MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhCRik7XG4gICAgZ2wuY2xlYXIoZ2wuU1RFTkNJTF9CVUZGRVJfQklUKTtcblxuICAgIC8vIFRoZSBzdGVuY2lsIHRlc3Qgd2lsbCBmYWlsIGFsd2F5cywgbWVhbmluZyB3ZSBzZXQgYWxsIHBpeGVscyBjb3ZlcmVkXG4gICAgLy8gYnkgdGhpcyBnZW9tZXRyeSB0byAweDgwLiBXZSB1c2UgdGhlIGhpZ2hlc3QgYml0IDB4ODAgdG8gbWFyayB0aGUgcmVnaW9uc1xuICAgIC8vIHdlIHdhbnQgdG8gZHJhdyBpbi4gQWxsIHBpeGVscyB0aGF0IGhhdmUgdGhpcyBiaXQgKm5vdCogc2V0IHdpbGwgbmV2ZXIgYmVcbiAgICAvLyBkcmF3biBpbi5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHhDMCwgMHg0MCk7XG4gICAgZ2wuc3RlbmNpbE1hc2soMHhDMCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLlJFUExBQ0UsIGdsLktFRVAsIGdsLktFRVApO1xuXG4gICAgLy8gRHJhdyB0aGUgY2xpcHBpbmcgbWFza1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLnRpbGVFeHRlbnRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgOCwgMCk7XG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgdGhpcy50aWxlRXh0ZW50QnVmZmVyLml0ZW1Db3VudCk7XG5cbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG4gICAgZ2wuc3RlbmNpbE9wKGdsLktFRVAsIGdsLktFRVAsIGdsLlJFUExBQ0UpO1xuICAgIGdsLnN0ZW5jaWxNYXNrKDB4MDApO1xuICAgIGdsLmNvbG9yTWFzayh0cnVlLCB0cnVlLCB0cnVlLCB0cnVlKTtcbn07XG5cbi8vIE92ZXJyaWRkZW4gYnkgaGVhZGxlc3MgdGVzdHMuXG5QYWludGVyLnByb3RvdHlwZS5wcmVwYXJlQnVmZmVycyA9IGZ1bmN0aW9uKCkge307XG5QYWludGVyLnByb3RvdHlwZS5iaW5kRGVmYXVsdEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xufTtcblxudmFyIGRyYXcgPSB7XG4gICAgc3ltYm9sOiByZXF1aXJlKCcuL2RyYXdfc3ltYm9sJyksXG4gICAgbGluZTogcmVxdWlyZSgnLi9kcmF3X2xpbmUnKSxcbiAgICBmaWxsOiByZXF1aXJlKCcuL2RyYXdfZmlsbCcpLFxuICAgIHJhc3RlcjogcmVxdWlyZSgnLi9kcmF3X3Jhc3RlcicpLFxuICAgIGJhY2tncm91bmQ6IHJlcXVpcmUoJy4vZHJhd19iYWNrZ3JvdW5kJyksXG4gICAgZGVidWc6IHJlcXVpcmUoJy4vZHJhd19kZWJ1ZycpLFxuICAgIHZlcnRpY2VzOiByZXF1aXJlKCcuL2RyYXdfdmVydGljZXMnKVxufTtcblxuUGFpbnRlci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24oc3R5bGUsIG9wdGlvbnMpIHtcbiAgICB0aGlzLnN0eWxlID0gc3R5bGU7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIHRoaXMubGluZUF0bGFzID0gc3R5bGUubGluZUF0bGFzO1xuXG4gICAgdGhpcy5zcHJpdGVBdGxhcyA9IHN0eWxlLnNwcml0ZUF0bGFzO1xuICAgIHRoaXMuc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHN0eWxlLnNwcml0ZSk7XG5cbiAgICB0aGlzLmdseXBoQXRsYXMgPSBzdHlsZS5nbHlwaEF0bGFzO1xuICAgIHRoaXMuZ2x5cGhBdGxhcy5iaW5kKHRoaXMuZ2wpO1xuXG4gICAgdGhpcy5mcmFtZUhpc3RvcnkucmVjb3JkKHRoaXMudHJhbnNmb3JtLnpvb20pO1xuXG4gICAgdGhpcy5wcmVwYXJlQnVmZmVycygpO1xuICAgIHRoaXMuY2xlYXJDb2xvcigpO1xuXG4gICAgZm9yICh2YXIgaSA9IHN0eWxlLl9ncm91cHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGdyb3VwID0gc3R5bGUuX2dyb3Vwc1tpXTtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHN0eWxlLnNvdXJjZXNbZ3JvdXAuc291cmNlXTtcblxuICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyU3RlbmNpbCgpO1xuICAgICAgICAgICAgc291cmNlLnJlbmRlcihncm91cCwgdGhpcyk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChncm91cC5zb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3TGF5ZXJzKGdyb3VwLCB0aGlzLmlkZW50aXR5TWF0cml4KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdUaWxlID0gZnVuY3Rpb24odGlsZSwgbGF5ZXJzKSB7XG4gICAgdGhpcy5zZXRFeHRlbnQodGlsZS50aWxlRXh0ZW50KTtcbiAgICB0aGlzLmRyYXdDbGlwcGluZ01hc2sodGlsZSk7XG4gICAgdGhpcy5kcmF3TGF5ZXJzKGxheWVycywgdGlsZS5wb3NNYXRyaXgsIHRpbGUpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kZWJ1Zykge1xuICAgICAgICBkcmF3LmRlYnVnKHRoaXMsIHRpbGUpO1xuICAgIH1cbn07XG5cblBhaW50ZXIucHJvdG90eXBlLmRyYXdMYXllcnMgPSBmdW5jdGlvbihsYXllcnMsIG1hdHJpeCwgdGlsZSkge1xuICAgIGZvciAodmFyIGkgPSBsYXllcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5oaWRkZW4pXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBkcmF3W2xheWVyLnR5cGVdKHRoaXMsIGxheWVyLCBtYXRyaXgsIHRpbGUpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmVydGljZXMpIHtcbiAgICAgICAgICAgIGRyYXcudmVydGljZXModGhpcywgbGF5ZXIsIG1hdHJpeCwgdGlsZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBEcmF3cyBub24tb3BhcXVlIGFyZWFzLiBUaGlzIGlzIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG5QYWludGVyLnByb3RvdHlwZS5kcmF3U3RlbmNpbEJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuc3dpdGNoU2hhZGVyKHRoaXMuZmlsbFNoYWRlciwgdGhpcy5pZGVudGl0eU1hdHJpeCk7XG5cbiAgICAvLyBCbGVuZCB0byB0aGUgZnJvbnQsIG5vdCB0aGUgYmFjay5cbiAgICBnbC5ibGVuZEZ1bmMoZ2wuT05FLCBnbC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcbiAgICBnbC5zdGVuY2lsTWFzaygweDAwKTtcbiAgICBnbC5zdGVuY2lsRnVuYyhnbC5FUVVBTCwgMHg4MCwgMHg4MCk7XG5cbiAgICAvLyBEcncgdGhlIGZpbGxpbmcgcXVhZCB3aGVyZSB0aGUgc3RlbmNpbCBidWZmZXIgaXNuJ3Qgc2V0LlxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLmJhY2tncm91bmRCdWZmZXIpO1xuICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5maWxsU2hhZGVyLmFfcG9zLCB0aGlzLmJhY2tncm91bmRCdWZmZXIuaXRlbVNpemUsIGdsLlNIT1JULCBmYWxzZSwgMCwgMCk7XG4gICAgZ2wudW5pZm9ybTRmdih0aGlzLmZpbGxTaGFkZXIudV9jb2xvciwgWzAsIDAsIDAsIDAuNV0pO1xuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIHRoaXMuYmFja2dyb3VuZEJ1ZmZlci5pdGVtQ291bnQpO1xuXG4gICAgLy8gUmV2ZXJ0IGJsZW5kaW5nIG1vZGUgdG8gYmxlbmQgdG8gdGhlIGJhY2suXG4gICAgZ2wuYmxlbmRGdW5jKGdsLk9ORV9NSU5VU19EU1RfQUxQSEEsIGdsLk9ORSk7XG59O1xuXG5QYWludGVyLnByb3RvdHlwZS50cmFuc2xhdGVNYXRyaXggPSBmdW5jdGlvbihtYXRyaXgsIHRpbGUsIHRyYW5zbGF0ZSwgYW5jaG9yKSB7XG4gICAgaWYgKCF0cmFuc2xhdGVbMF0gJiYgIXRyYW5zbGF0ZVsxXSkgcmV0dXJuIG1hdHJpeDtcblxuICAgIGlmIChhbmNob3IgPT09ICd2aWV3cG9ydCcpIHtcbiAgICAgICAgdmFyIHNpbkEgPSBNYXRoLnNpbigtdGhpcy50cmFuc2Zvcm0uYW5nbGUpO1xuICAgICAgICB2YXIgY29zQSA9IE1hdGguY29zKC10aGlzLnRyYW5zZm9ybS5hbmdsZSk7XG4gICAgICAgIHRyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVswXSAqIGNvc0EgLSB0cmFuc2xhdGVbMV0gKiBzaW5BLFxuICAgICAgICAgICAgdHJhbnNsYXRlWzBdICogc2luQSArIHRyYW5zbGF0ZVsxXSAqIGNvc0FcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICB2YXIgdGlsZVBpeGVsUmF0aW8gPSB0aGlzLnRyYW5zZm9ybS5zY2FsZSAvICgxIDw8IHRpbGUuY29vcmQueikgLyAodGlsZS50aWxlRXh0ZW50IC8gdGlsZS50aWxlU2l6ZSk7XG4gICAgdmFyIHRyYW5zbGF0aW9uID0gW1xuICAgICAgICB0cmFuc2xhdGVbMF0gLyB0aWxlUGl4ZWxSYXRpbyxcbiAgICAgICAgdHJhbnNsYXRlWzFdIC8gdGlsZVBpeGVsUmF0aW8sXG4gICAgICAgIDBcbiAgICBdO1xuXG4gICAgdmFyIHRyYW5zbGF0ZWRNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcbiAgICBtYXQ0LnRyYW5zbGF0ZSh0cmFuc2xhdGVkTWF0cml4LCBtYXRyaXgsIHRyYW5zbGF0aW9uKTtcbiAgICByZXR1cm4gdHJhbnNsYXRlZE1hdHJpeDtcbn07XG5cblBhaW50ZXIucHJvdG90eXBlLnNhdmVUZXh0dXJlID0gZnVuY3Rpb24odGV4dHVyZSkge1xuICAgIHZhciB0ZXh0dXJlcyA9IHRoaXMucmV1c2FibGVUZXh0dXJlc1t0ZXh0dXJlLnNpemVdO1xuICAgIGlmICghdGV4dHVyZXMpIHtcbiAgICAgICAgdGhpcy5yZXVzYWJsZVRleHR1cmVzW3RleHR1cmUuc2l6ZV0gPSBbdGV4dHVyZV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHVyZXMucHVzaCh0ZXh0dXJlKTtcbiAgICB9XG59O1xuXG5cblBhaW50ZXIucHJvdG90eXBlLmdldFRleHR1cmUgPSBmdW5jdGlvbihzaXplKSB7XG4gICAgdmFyIHRleHR1cmVzID0gdGhpcy5yZXVzYWJsZVRleHR1cmVzW3NpemVdO1xuICAgIHJldHVybiB0ZXh0dXJlcyAmJiB0ZXh0dXJlcy5sZW5ndGggPiAwID8gdGV4dHVyZXMucG9wKCkgOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGdsaWZ5ID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBcImRlYnVnXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBmbG9hdCB1X3BvaW50c2l6ZTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcyxzdGVwKDMyNzY3LixhX3Bvcy54KSwxKTtnbF9Qb2ludFNpemU9dV9wb2ludHNpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZvaWQgbWFpbigpe2dsX0ZyYWdDb2xvcj11X2NvbG9yO31cIn0sXG4gICAgXCJkb3RcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBmbG9hdCB1X3NpemU7YXR0cmlidXRlIHZlYzIgYV9wb3M7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT11X3NpemU7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3VuaWZvcm0gZmxvYXQgdV9ibHVyO3ZvaWQgbWFpbigpe2Zsb2F0IGEsYjthPWxlbmd0aChnbF9Qb2ludENvb3JkLS41KTtiPXNtb290aHN0ZXAoLjUsLjUtdV9ibHVyLGEpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmI7fVwifSxcbiAgICBcImZpbGxcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2dsX1BvaW50U2l6ZT0yLjt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXVfY29sb3I7fVwifSxcbiAgICBcImdhdXNzaWFuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X29mZnNldDt2YXJ5aW5nIHZlYzIgYVszXTt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dmVjMiBiPWdsX1Bvc2l0aW9uLnh5LzIuKy41O2FbMF09YjthWzFdPWIrdV9vZmZzZXQqMS4xODI0MjU1MjM4MDYzNTYzO2FbMl09Yi11X29mZnNldCoxLjE4MjQyNTUyMzgwNjM1NjM7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGFbM107dm9pZCBtYWluKCl7dmVjNCBiPXZlYzQoMCk7Yis9dGV4dHVyZTJEKHVfaW1hZ2UsYVswXSkqLjQwMjYxOTk0Njg5NDI0NzQ2O2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMV0pKi4yOTg2OTAwMjY1NTI4NzYzO2IrPXRleHR1cmUyRCh1X2ltYWdlLGFbMl0pKi4yOTg2OTAwMjY1NTI4NzYzO2dsX0ZyYWdDb2xvcj1iO31cIn0sXG4gICAgXCJsaW5lXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW8sdV9leHRyYTt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGg7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBtYXQyIHVfYW50aWFsaWFzaW5nbWF0cml4O3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxlO2Q9YV9kYXRhLnh5O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTt2ZWM0IGY9dmVjNCh1X2xpbmV3aWR0aC5zKmQqLjAxNTg3MzAxNiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoZmxvb3IoYV9wb3MqLjUpK2YueHkvdV9yYXRpbywwLDEpO2Zsb2F0IGcsaCxpO2c9Z2xfUG9zaXRpb24ueS9nbF9Qb3NpdGlvbi53O2g9bGVuZ3RoKGQpL2xlbmd0aCh1X2FudGlhbGlhc2luZ21hdHJpeCpkKTtpPTEuLygxLi1nKnVfZXh0cmEpO2M9aSpoO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHZlYzIgdV9saW5ld2lkdGgsdV9kYXNoYXJyYXk7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2JsdXI7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiLGM7dm9pZCBtYWluKCl7ZmxvYXQgZCxlLGY7ZD1sZW5ndGgoYSkqdV9saW5ld2lkdGgucztlPXVfYmx1cipjO2Y9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtZSksdV9saW5ld2lkdGgucy1kKS9lLDAuLDEuKTtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJsaW5lcGF0dGVyblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfcmF0aW87dW5pZm9ybSB2ZWMyIHVfbGluZXdpZHRoO3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZSxmLGc7Yz1hX2RhdGEueHk7ZmxvYXQgZD1hX2RhdGEueioxMjguK2FfZGF0YS53O2U9bW9kKGFfcG9zLDIuKTtlLnk9c2lnbihlLnktLjUpO2E9ZTtmPWMqLjAxNTg3MzAxNjtnPXVfbGluZXdpZHRoLnMqZjtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPWQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5fc2l6ZV9hLHVfcGF0dGVybl9zaXplX2IsdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBmbG9hdCB1X3BvaW50LHVfYmx1cix1X2ZhZGUsdV9vcGFjaXR5O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGE7dmFyeWluZyBmbG9hdCBiO3ZvaWQgbWFpbigpe2Zsb2F0IGMsZCxlLGYsZyxoO2M9bGVuZ3RoKGEpKnVfbGluZXdpZHRoLnM7ZD1jbGFtcChtaW4oYy0odV9saW5ld2lkdGgudC11X2JsdXIpLHVfbGluZXdpZHRoLnMtYykvdV9ibHVyLDAuLDEuKTtlPW1vZChiL3VfcGF0dGVybl9zaXplX2EueCwxLik7Zj1tb2QoYi91X3BhdHRlcm5fc2l6ZV9iLngsMS4pO2c9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYS55O2g9LjUrYS55KnVfbGluZXdpZHRoLnMvdV9wYXR0ZXJuX3NpemVfYi55O3ZlYzIgaSxqO2k9bWl4KHVfcGF0dGVybl90bF9hLHVfcGF0dGVybl9icl9hLHZlYzIoZSxnKSk7aj1taXgodV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2IsdmVjMihmLGgpKTt2ZWM0IGs9bWl4KHRleHR1cmUyRCh1X2ltYWdlLGkpLHRleHR1cmUyRCh1X2ltYWdlLGopLHVfZmFkZSk7ZCo9dV9vcGFjaXR5O2dsX0ZyYWdDb2xvcj1rKmQ7fVwifSxcbiAgICBcImxpbmVzZGZwYXR0ZXJuXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3M7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aCx1X3BhdHRlcm5zY2FsZV9hLHVfcGF0dGVybnNjYWxlX2I7dW5pZm9ybSBmbG9hdCB1X3JhdGlvLHVfdGV4X3lfYSx1X3RleF95X2I7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe3ZlYzIgZCxmO2Q9YV9kYXRhLnh5O2Zsb2F0IGU9YV9kYXRhLnoqMTI4LithX2RhdGEudztmPW1vZChhX3BvcywyLik7Zi55PXNpZ24oZi55LS41KTthPWY7dmVjNCBnPXZlYzQodV9saW5ld2lkdGgucypkKi4wMTU4NzMwMTYsMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGZsb29yKGFfcG9zKi41KStnLnh5L3VfcmF0aW8sMCwxKTtiPXZlYzIoZSp1X3BhdHRlcm5zY2FsZV9hLngsZi55KnVfcGF0dGVybnNjYWxlX2EueSt1X3RleF95X2EpO2M9dmVjMihlKnVfcGF0dGVybnNjYWxlX2IueCxmLnkqdV9wYXR0ZXJuc2NhbGVfYi55K3VfdGV4X3lfYik7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjMiB1X2xpbmV3aWR0aDt1bmlmb3JtIHZlYzQgdV9jb2xvcjt1bmlmb3JtIGZsb2F0IHVfYmx1cix1X3NkZmdhbW1hLHVfbWl4O3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dmFyeWluZyB2ZWMyIGEsYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmLGcsaDtkPWxlbmd0aChhKSp1X2xpbmV3aWR0aC5zO2U9Y2xhbXAobWluKGQtKHVfbGluZXdpZHRoLnQtdV9ibHVyKSx1X2xpbmV3aWR0aC5zLWQpL3VfYmx1ciwwLiwxLik7Zj10ZXh0dXJlMkQodV9pbWFnZSxiKS5hO2c9dGV4dHVyZTJEKHVfaW1hZ2UsYykuYTtoPW1peChmLGcsdV9taXgpO2UqPXNtb290aHN0ZXAoLjUtdV9zZGZnYW1tYSwuNSt1X3NkZmdhbW1hLGgpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmU7fVwifSxcbiAgICBcIm91dGxpbmVcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfd29ybGQ7dmFyeWluZyB2ZWMyIGE7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4pLzIuKnVfd29ybGQ7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gdmVjNCB1X2NvbG9yO3ZhcnlpbmcgdmVjMiBhO3ZvaWQgbWFpbigpe2Zsb2F0IGIsYztiPWxlbmd0aChhLWdsX0ZyYWdDb29yZC54eSk7Yz1zbW9vdGhzdGVwKDEuLDAuLGIpO2dsX0ZyYWdDb2xvcj11X2NvbG9yKmM7fVwifSxcbiAgICBcInBhdHRlcm5cIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBtYXQzIHVfcGF0dGVybm1hdHJpeF9hLHVfcGF0dGVybm1hdHJpeF9iO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2E9KHVfcGF0dGVybm1hdHJpeF9hKnZlYzMoYV9wb3MsMSkpLnh5O2I9KHVfcGF0dGVybm1hdHJpeF9iKnZlYzMoYV9wb3MsMSkpLnh5O31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIGZsb2F0IHVfb3BhY2l0eSx1X21peDt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3RsX2EsdV9wYXR0ZXJuX2JyX2EsdV9wYXR0ZXJuX3RsX2IsdV9wYXR0ZXJuX2JyX2I7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgYSxiO3ZvaWQgbWFpbigpe3ZlYzIgYyxkLGYsZztjPW1vZChhLDEuKTtkPW1peCh1X3BhdHRlcm5fdGxfYSx1X3BhdHRlcm5fYnJfYSxjKTt2ZWM0IGUsaDtlPXRleHR1cmUyRCh1X2ltYWdlLGQpO2Y9bW9kKGIsMS4pO2c9bWl4KHVfcGF0dGVybl90bF9iLHVfcGF0dGVybl9icl9iLGYpO2g9dGV4dHVyZTJEKHVfaW1hZ2UsZyk7Z2xfRnJhZ0NvbG9yPW1peChlLGgsdV9taXgpKnVfb3BhY2l0eTt9XCJ9LFxuICAgIFwicmFzdGVyXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3RsX3BhcmVudDt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfcGFyZW50LHVfYnVmZmVyX3NjYWxlO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfdGV4dHVyZV9wb3M7dmFyeWluZyB2ZWMyIGEsYjt2b2lkIG1haW4oKXtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7YT0oYV90ZXh0dXJlX3Bvcy8zMjc2Ny4tLjUpL3VfYnVmZmVyX3NjYWxlKy41O2I9YSp1X3NjYWxlX3BhcmVudCt1X3RsX3BhcmVudDt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X29wYWNpdHkwLHVfb3BhY2l0eTEsdV9icmlnaHRuZXNzX2xvdyx1X2JyaWdodG5lc3NfaGlnaCx1X3NhdHVyYXRpb25fZmFjdG9yLHVfY29udHJhc3RfZmFjdG9yO3VuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2UwLHVfaW1hZ2UxO3ZhcnlpbmcgdmVjMiBhLGI7dW5pZm9ybSB2ZWMzIHVfc3Bpbl93ZWlnaHRzO3ZvaWQgbWFpbigpe3ZlYzQgYyxkLGU7Yz10ZXh0dXJlMkQodV9pbWFnZTAsYSk7ZD10ZXh0dXJlMkQodV9pbWFnZTEsYik7ZT1jKnVfb3BhY2l0eTArZCp1X29wYWNpdHkxO3ZlYzMgZixoLGk7Zj1lLnJnYjtmPXZlYzMoZG90KGYsdV9zcGluX3dlaWdodHMueHl6KSxkb3QoZix1X3NwaW5fd2VpZ2h0cy56eHkpLGRvdChmLHVfc3Bpbl93ZWlnaHRzLnl6eCkpO2Zsb2F0IGc9KGUucitlLmcrZS5iKS8zLjtmKz0oZy1mKSp1X3NhdHVyYXRpb25fZmFjdG9yO2Y9KGYtLjUpKnVfY29udHJhc3RfZmFjdG9yKy41O2g9dmVjMyh1X2JyaWdodG5lc3NfbG93KTtpPXZlYzModV9icmlnaHRuZXNzX2hpZ2gpO2dsX0ZyYWdDb2xvcj12ZWM0KG1peChoLGksZiksZS5hKTt9XCJ9LFxuICAgIFwiaWNvblwiOiB7XCJ2ZXJ0ZXhcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zLGFfb2Zmc2V0O2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTEsYV9kYXRhMjt1bmlmb3JtIG1hdDQgdV9tYXRyaXgsdV9leG1hdHJpeDt1bmlmb3JtIGZsb2F0IHVfem9vbSx1X2ZhZGVkaXN0LHVfbWluZmFkZXpvb20sdV9tYXhmYWRlem9vbSx1X2ZhZGV6b29tLHVfb3BhY2l0eSx1X2V4dHJhO3VuaWZvcm0gYm9vbCB1X3NrZXdlZDt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYjt2b2lkIG1haW4oKXt2ZWMyIGMsZTtjPWFfZGF0YTEueHk7ZmxvYXQgZCxmLGcsaCxpLGo7ZD1hX2RhdGExWzJdO2U9YV9kYXRhMi5zdDtmPWVbMF07Zz1lWzFdO2g9MTAuO2k9Mi4tc3RlcChmLHVfem9vbSktKDEuLXN0ZXAoZyx1X3pvb20pKTtqPWNsYW1wKCh1X2ZhZGV6b29tLWQpL3VfZmFkZWRpc3QsMC4sMS4pO2lmKHVfZmFkZWRpc3Q+PTAuKWI9ajtlbHNlIGI9MS4tajtpZih1X21heGZhZGV6b29tPGQpYj0wLjtpZih1X21pbmZhZGV6b29tPj1kKWI9MS47aSs9c3RlcChiLDAuKTtpZih1X3NrZXdlZCl7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4sMCwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zK2sueHksMCwxKTtnbF9Qb3NpdGlvbi56Kz1pKmdsX1Bvc2l0aW9uLnc7fWVsc2V7dmVjNCBrPXVfZXhtYXRyaXgqdmVjNChhX29mZnNldC82NC4saSwwKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSkrazt9YT1jL3VfdGV4c2l6ZTtiKj11X29wYWNpdHk7fVwiLFwiZnJhZ21lbnRcIjpcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O3VuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGI7dm9pZCBtYWluKCl7Z2xfRnJhZ0NvbG9yPXRleHR1cmUyRCh1X3RleHR1cmUsYSkqYjt9XCJ9LFxuICAgIFwic2RmXCI6IHtcInZlcnRleFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7YXR0cmlidXRlIHZlYzIgYV9wb3MsYV9vZmZzZXQ7YXR0cmlidXRlIHZlYzQgYV9kYXRhMSxhX2RhdGEyO3VuaWZvcm0gbWF0NCB1X21hdHJpeCx1X2V4bWF0cml4O3VuaWZvcm0gZmxvYXQgdV96b29tLHVfZmFkZWRpc3QsdV9taW5mYWRlem9vbSx1X21heGZhZGV6b29tLHVfZmFkZXpvb20sdV9leHRyYTt1bmlmb3JtIGJvb2wgdV9za2V3ZWQ7dW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt2YXJ5aW5nIHZlYzIgYTt2YXJ5aW5nIGZsb2F0IGIsYzt2b2lkIG1haW4oKXt2ZWMyIGQsZjtkPWFfZGF0YTEueHk7ZmxvYXQgZSxnLGgsaSxqLGssbDtlPWFfZGF0YTFbMl07Zj1hX2RhdGEyLnN0O2c9ZlswXTtoPWZbMV07aT0yLi1zdGVwKGcsdV96b29tKS0oMS4tc3RlcChoLHVfem9vbSkpO2o9Y2xhbXAoKHVfZmFkZXpvb20tZSkvdV9mYWRlZGlzdCwwLiwxLik7aWYodV9mYWRlZGlzdD49MC4pYj1qO2Vsc2UgYj0xLi1qO2lmKHVfbWF4ZmFkZXpvb208ZSliPTAuO2lmKHVfbWluZmFkZXpvb20+PWUpYj0xLjtpKz1zdGVwKGIsMC4pO2lmKHVfc2tld2VkKXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LiwwLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3Mray54eSwwLDEpO2dsX1Bvc2l0aW9uLnorPWkqZ2xfUG9zaXRpb24udzt9ZWxzZXt2ZWM0IGs9dV9leG1hdHJpeCp2ZWM0KGFfb2Zmc2V0LzY0LixpLDApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKStrO31rPWdsX1Bvc2l0aW9uLnkvZ2xfUG9zaXRpb24udztsPTEuLygxLi1rKnVfZXh0cmEpO2M9bDthPWQvdV90ZXhzaXplO31cIixcImZyYWdtZW50XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDt1bmlmb3JtIHNhbXBsZXIyRCB1X3RleHR1cmU7dW5pZm9ybSB2ZWM0IHVfY29sb3I7dW5pZm9ybSBmbG9hdCB1X2J1ZmZlcix1X2dhbW1hO3ZhcnlpbmcgdmVjMiBhO3ZhcnlpbmcgZmxvYXQgYixjO3ZvaWQgbWFpbigpe2Zsb2F0IGQsZSxmO2Q9dV9nYW1tYSpjO2U9dGV4dHVyZTJEKHVfdGV4dHVyZSxhKS5hO2Y9c21vb3Roc3RlcCh1X2J1ZmZlci1kLHVfYnVmZmVyK2QsZSkqYjtnbF9GcmFnQ29sb3I9dV9jb2xvcipmO31cIn0sXG4gICAgXCJjb2xsaXNpb25ib3hcIjoge1widmVydGV4XCI6XCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDthdHRyaWJ1dGUgdmVjMiBhX3BvcyxhX2V4dHJ1ZGUsYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGZsb2F0IHVfc2NhbGU7dmFyeWluZyBmbG9hdCBhLGI7dm9pZCBtYWluKCl7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcythX2V4dHJ1ZGUvdV9zY2FsZSwwLDEpO2E9YV9kYXRhLng7Yj1hX2RhdGEueTt9XCIsXCJmcmFnbWVudFwiOlwicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7dW5pZm9ybSBmbG9hdCB1X3pvb20sdV9tYXh6b29tO3ZhcnlpbmcgZmxvYXQgYSxiO3ZvaWQgbWFpbigpe2Zsb2F0IGM9LjU7Z2xfRnJhZ0NvbG9yPXZlYzQoMCwxLDAsMSkqYztpZihiPnVfem9vbSlnbF9GcmFnQ29sb3I9dmVjNCgxLDAsMCwxKSpjO2lmKHVfem9vbT49YSlnbF9GcmFnQ29sb3I9dmVjNCgwLDAsMCwxKSpjKi4yNTtpZihiPj11X21heHpvb20pZ2xfRnJhZ0NvbG9yPXZlYzQoMCwwLDEsMSkqYyouMjt9XCJ9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIEV2ZW50ZWQgPSByZXF1aXJlKCcuLi91dGlsL2V2ZW50ZWQnKTtcbnZhciBUaWxlUHlyYW1pZCA9IHJlcXVpcmUoJy4vdGlsZV9weXJhbWlkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcbnZhciB1cmxSZXNvbHZlID0gcmVxdWlyZSgncmVzb2x2ZS11cmwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBHZW9KU09OU291cmNlO1xuXG4vKipcbiAqIENyZWF0ZSBhIEdlb0pTT04gZGF0YSBzb3VyY2UgaW5zdGFuY2UgZ2l2ZW4gYW4gb3B0aW9ucyBvYmplY3RcbiAqIEBjbGFzcyBHZW9KU09OU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IG9wdGlvbnMuZGF0YSBBIEdlb0pTT04gZGF0YSBvYmplY3Qgb3IgVVJMIHRvIGl0LiBUaGUgbGF0dGVyIGlzIHByZWZlcmFibGUgaW4gY2FzZSBvZiBsYXJnZSBHZW9KU09OIGZpbGVzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heHpvb209MTRdIE1heGltdW0gem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgYXQuXG4gKiBAZXhhbXBsZVxuICogdmFyIHNvdXJjZU9iaiA9IG5ldyBtYXBib3hnbC5HZW9KU09OU291cmNlKHtcbiAqICAgIGRhdGE6IHtcbiAqICAgICAgICBcInR5cGVcIjogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICogICAgICAgIFwiZmVhdHVyZXNcIjogW3tcbiAqICAgICAgICAgICAgXCJ0eXBlXCI6IFwiRmVhdHVyZVwiLFxuICogICAgICAgICAgICBcImdlb21ldHJ5XCI6IHtcbiAqICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIlBvaW50XCIsXG4gKiAgICAgICAgICAgICAgICBcImNvb3JkaW5hdGVzXCI6IFtcbiAqICAgICAgICAgICAgICAgICAgICAtNzYuNTMwNjMyOTcyNzE3MjksXG4gKiAgICAgICAgICAgICAgICAgICAgMzkuMTgxNzQwNzc5OTQxMDhcbiAqICAgICAgICAgICAgICAgIF1cbiAqICAgICAgICAgICAgfVxuICogICAgICAgIH1dXG4gKiAgICB9XG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBHZW9KU09OU291cmNlKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIHRoaXMuX2RhdGEgPSBvcHRpb25zLmRhdGE7XG5cbiAgICBpZiAob3B0aW9ucy5tYXh6b29tICE9PSB1bmRlZmluZWQpIHRoaXMubWF4em9vbSA9IG9wdGlvbnMubWF4em9vbTtcblxuICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICB0aWxlU2l6ZTogNTEyLFxuICAgICAgICBtaW56b29tOiB0aGlzLm1pbnpvb20sXG4gICAgICAgIG1heHpvb206IHRoaXMubWF4em9vbSxcbiAgICAgICAgY2FjaGVTaXplOiAyMCxcbiAgICAgICAgbG9hZDogdGhpcy5fbG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICB1bmxvYWQ6IHRoaXMuX3VubG9hZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgYWRkOiB0aGlzLl9hZGRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpXG4gICAgfSk7XG59XG5cbkdlb0pTT05Tb3VyY2UucHJvdG90eXBlID0gdXRpbC5pbmhlcml0KEV2ZW50ZWQsIC8qKiBAbGVuZHMgR2VvSlNPTlNvdXJjZS5wcm90b3R5cGUgKi97XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAxNCxcbiAgICBfZGlydHk6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgc291cmNlIGdlb2pzb24gZGF0YSBhbmQgcmVyZW5kZXIgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGRhdGEgQSBHZW9KU09OIGRhdGEgb2JqZWN0IG9yIFVSTCB0byBpdC4gVGhlIGxhdHRlciBpcyBwcmVmZXJhYmxlIGluIGNhc2Ugb2YgbGFyZ2UgR2VvSlNPTiBmaWxlcy5cbiAgICAgKiBAcmV0dXJucyB7R2VvSlNPTlNvdXJjZX0gdGhpc1xuICAgICAqL1xuICAgIHNldERhdGE6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScpO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcClcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHRoaXMubWFwLnRyYW5zZm9ybSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkZWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX2RpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEYXRhKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVuZGVyOiBTb3VyY2UuX3JlbmRlclRpbGVzLFxuICAgIGZlYXR1cmVzQXQ6IFNvdXJjZS5fdmVjdG9yRmVhdHVyZXNBdCxcblxuICAgIF91cGRhdGVEYXRhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkYXRhID0gdXJsUmVzb2x2ZSh3aW5kb3cubG9jYXRpb24uaHJlZiwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdwYXJzZSBnZW9qc29uJywge1xuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHRpbGVTaXplOiA1MTIsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb21cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyKSB7XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcblxuICAgICAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuXG4gICAgX2xvYWRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHZhciBvdmVyc2NhbGluZyA9IHRpbGUuY29vcmQueiA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHRpbGUuY29vcmQueiAtIHRoaXMubWF4em9vbSkgOiAxO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgdWlkOiB0aWxlLnVpZCxcbiAgICAgICAgICAgIGNvb3JkOiB0aWxlLmNvb3JkLFxuICAgICAgICAgICAgem9vbTogdGlsZS5jb29yZC56LFxuICAgICAgICAgICAgbWF4Wm9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgdGlsZVNpemU6IDUxMixcbiAgICAgICAgICAgIHNvdXJjZTogdGhpcy5pZCxcbiAgICAgICAgICAgIG92ZXJzY2FsaW5nOiBvdmVyc2NhbGluZyxcbiAgICAgICAgICAgIGFuZ2xlOiB0aGlzLm1hcC50cmFuc2Zvcm0uYW5nbGUsXG4gICAgICAgICAgICBwaXRjaDogdGhpcy5tYXAudHJhbnNmb3JtLnBpdGNoLFxuICAgICAgICAgICAgY29sbGlzaW9uRGVidWc6IHRoaXMubWFwLmNvbGxpc2lvbkRlYnVnXG4gICAgICAgIH07XG5cbiAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIGdlb2pzb24gdGlsZScsIHBhcmFtcywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG5cbiAgICAgICAgICAgIHRpbGUudW5sb2FkVmVjdG9yRGF0YSh0aGlzLm1hcC5wYWludGVyKTtcblxuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGlsZS5sb2FkVmVjdG9yRGF0YShkYXRhKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5sb2FkJywge3RpbGU6IHRpbGV9KTtcblxuICAgICAgICB9LmJpbmQodGhpcyksIHRoaXMud29ya2VySUQpO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCd2ZWN0b3ItdGlsZScpLlZlY3RvclRpbGVGZWF0dXJlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlb0pTT05XcmFwcGVyO1xuXG4vLyBjb25mb3JtIHRvIHZlY3RvcnRpbGUgYXBpXG5mdW5jdGlvbiBHZW9KU09OV3JhcHBlcihmZWF0dXJlcykge1xuICAgIHRoaXMuZmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICB0aGlzLmxlbmd0aCA9IGZlYXR1cmVzLmxlbmd0aDtcbn1cblxuR2VvSlNPTldyYXBwZXIucHJvdG90eXBlLmZlYXR1cmUgPSBmdW5jdGlvbihpKSB7XG4gICAgcmV0dXJuIG5ldyBGZWF0dXJlV3JhcHBlcih0aGlzLmZlYXR1cmVzW2ldKTtcbn07XG5cbmZ1bmN0aW9uIEZlYXR1cmVXcmFwcGVyKGZlYXR1cmUpIHtcbiAgICB0aGlzLnR5cGUgPSBmZWF0dXJlLnR5cGU7XG4gICAgdGhpcy5yYXdHZW9tZXRyeSA9IGZlYXR1cmUudHlwZSA9PT0gMSA/IFtmZWF0dXJlLmdlb21ldHJ5XSA6IGZlYXR1cmUuZ2VvbWV0cnk7XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gZmVhdHVyZS50YWdzO1xuICAgIHRoaXMuZXh0ZW50ID0gNDA5Njtcbn1cblxuRmVhdHVyZVdyYXBwZXIucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByaW5ncyA9IHRoaXMucmF3R2VvbWV0cnk7XG4gICAgdGhpcy5nZW9tZXRyeSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmluZyA9IHJpbmdzW2ldLFxuICAgICAgICAgICAgbmV3UmluZyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG5ld1JpbmcucHVzaChuZXcgUG9pbnQocmluZ1tqXVswXSwgcmluZ1tqXVsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2VvbWV0cnkucHVzaChuZXdSaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnk7XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5nZW9tZXRyeSkgdGhpcy5sb2FkR2VvbWV0cnkoKTtcblxuICAgIHZhciByaW5ncyA9IHRoaXMuZ2VvbWV0cnksXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHJpbmcgPSByaW5nc1tpXTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjb29yZCA9IHJpbmdbal07XG5cbiAgICAgICAgICAgIHgxID0gTWF0aC5taW4oeDEsIGNvb3JkLngpO1xuICAgICAgICAgICAgeDIgPSBNYXRoLm1heCh4MiwgY29vcmQueCk7XG4gICAgICAgICAgICB5MSA9IE1hdGgubWluKHkxLCBjb29yZC55KTtcbiAgICAgICAgICAgIHkyID0gTWF0aC5tYXgoeTIsIGNvb3JkLnkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4MSwgeTEsIHgyLCB5Ml07XG59O1xuXG5GZWF0dXJlV3JhcHBlci5wcm90b3R5cGUudG9HZW9KU09OID0gVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4vc291cmNlJyk7XG52YXIgbm9ybWFsaXplVVJMID0gcmVxdWlyZSgnLi4vdXRpbC9tYXBib3gnKS5ub3JtYWxpemVUaWxlVVJMO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhc3RlclRpbGVTb3VyY2U7XG5cbmZ1bmN0aW9uIFJhc3RlclRpbGVTb3VyY2Uob3B0aW9ucykge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHV0aWwucGljayhvcHRpb25zLCBbJ3VybCcsICd0aWxlU2l6ZSddKSk7XG5cbiAgICBTb3VyY2UuX2xvYWRUaWxlSlNPTi5jYWxsKHRoaXMsIG9wdGlvbnMpO1xufVxuXG5SYXN0ZXJUaWxlU291cmNlLnByb3RvdHlwZSA9IHV0aWwuaW5oZXJpdChFdmVudGVkLCB7XG4gICAgbWluem9vbTogMCxcbiAgICBtYXh6b29tOiAyMixcbiAgICB0aWxlU2l6ZTogNTEyLFxuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgb25BZGQ6IGZ1bmN0aW9uKG1hcCkge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICB9LFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3B5cmFtaWQgJiYgdGhpcy5fcHlyYW1pZC5sb2FkZWQoKTtcbiAgICB9LFxuXG4gICAgdXBkYXRlOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgaWYgKHRoaXMuX3B5cmFtaWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5cmFtaWQudXBkYXRlKHRoaXMudXNlZCwgdHJhbnNmb3JtLCB0aGlzLm1hcC5zdHlsZS5yYXN0ZXJGYWRlRHVyYXRpb24pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcblxuICAgIF9sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBhamF4LmdldEltYWdlKG5vcm1hbGl6ZVVSTCh0aWxlLmNvb3JkLnVybCh0aGlzLnRpbGVzKSwgdGhpcy51cmwpLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICAgICAgaWYgKHRpbGUuYWJvcnRlZClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUuZXJyb3InLCB7dGlsZTogdGlsZX0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGdsID0gdGhpcy5tYXAucGFpbnRlci5nbDtcbiAgICAgICAgICAgIHRpbGUudGV4dHVyZSA9IHRoaXMubWFwLnBhaW50ZXIuZ2V0VGV4dHVyZShpbWcud2lkdGgpO1xuICAgICAgICAgICAgaWYgKHRpbGUudGV4dHVyZSkge1xuICAgICAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRpbGUudGV4dHVyZSk7XG4gICAgICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCAwLCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aWxlLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSX01JUE1BUF9ORUFSRVNUKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGltZyk7XG4gICAgICAgICAgICAgICAgdGlsZS50ZXh0dXJlLnNpemUgPSBpbWcud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnbC5nZW5lcmF0ZU1pcG1hcChnbC5URVhUVVJFXzJEKTtcblxuICAgICAgICAgICAgdGlsZS50aW1lQWRkZWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHRoaXMubWFwLmFuaW1hdGlvbkxvb3Auc2V0KHRoaXMuc3R5bGUucmFzdGVyRmFkZUR1cmF0aW9uKTtcblxuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGlsZS5sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3RpbGUubG9hZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9hYm9ydFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS5hYm9ydGVkID0gdHJ1ZTtcbiAgICB9LFxuXG4gICAgX2FkZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmFkZCcsIHt0aWxlOiB0aWxlfSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmVUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5yZW1vdmUnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfdW5sb2FkVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICBpZiAodGlsZS50ZXh0dXJlKSB0aGlzLm1hcC5wYWludGVyLnNhdmVUZXh0dXJlKHRpbGUudGV4dHVyZSk7XG4gICAgfSxcblxuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIFtdKTtcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4Jyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFRpbGVQeXJhbWlkID0gcmVxdWlyZSgnLi90aWxlX3B5cmFtaWQnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBub3JtYWxpemVVUkwgPSByZXF1aXJlKCcuLi91dGlsL21hcGJveCcpLm5vcm1hbGl6ZVNvdXJjZVVSTDtcblxuZXhwb3J0cy5fbG9hZFRpbGVKU09OID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciBsb2FkZWQgPSBmdW5jdGlvbihlcnIsIHRpbGVKU09OKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKHRpbGVKU09OLFxuICAgICAgICAgICAgWyd0aWxlcycsICdtaW56b29tJywgJ21heHpvb20nLCAnYXR0cmlidXRpb24nXSkpO1xuXG4gICAgICAgIHRoaXMuX3B5cmFtaWQgPSBuZXcgVGlsZVB5cmFtaWQoe1xuICAgICAgICAgICAgdGlsZVNpemU6IHRoaXMudGlsZVNpemUsXG4gICAgICAgICAgICBjYWNoZVNpemU6IDIwLFxuICAgICAgICAgICAgbWluem9vbTogdGhpcy5taW56b29tLFxuICAgICAgICAgICAgbWF4em9vbTogdGhpcy5tYXh6b29tLFxuICAgICAgICAgICAgcmVwYXJzZU92ZXJzY2FsZWQ6IHRoaXMucmVwYXJzZU92ZXJzY2FsZWQsXG4gICAgICAgICAgICBsb2FkOiB0aGlzLl9sb2FkVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgYWJvcnQ6IHRoaXMuX2Fib3J0VGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgdW5sb2FkOiB0aGlzLl91bmxvYWRUaWxlLmJpbmQodGhpcyksXG4gICAgICAgICAgICBhZGQ6IHRoaXMuX2FkZFRpbGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHJlbW92ZTogdGhpcy5fcmVtb3ZlVGlsZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcmVkb1BsYWNlbWVudDogdGhpcy5fcmVkb1RpbGVQbGFjZW1lbnQgPyB0aGlzLl9yZWRvVGlsZVBsYWNlbWVudC5iaW5kKHRoaXMpIDogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmlyZSgnbG9hZCcpO1xuICAgIH0uYmluZCh0aGlzKTtcblxuICAgIGlmIChvcHRpb25zLnVybCkge1xuICAgICAgICBhamF4LmdldEpTT04obm9ybWFsaXplVVJMKG9wdGlvbnMudXJsKSwgbG9hZGVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBicm93c2VyLmZyYW1lKGxvYWRlZC5iaW5kKHRoaXMsIG51bGwsIG9wdGlvbnMpKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl9yZW5kZXJUaWxlcyA9IGZ1bmN0aW9uKGxheWVycywgcGFpbnRlcikge1xuICAgIGlmICghdGhpcy5fcHlyYW1pZClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQucmVuZGVyZWRJRHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3B5cmFtaWQuZ2V0VGlsZShpZHNbaV0pLFxuICAgICAgICAgICAgLy8gY29vcmQgaXMgZGlmZmVyZW50IHRoYW4gdGlsZS5jb29yZCBmb3Igd3JhcHBlZCB0aWxlcyBzaW5jZSB0aGUgYWN0dWFsXG4gICAgICAgICAgICAvLyB0aWxlIG9iamVjdCBpcyBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlIHZpc2libGUgY29waWVzIG9mIHRoYXQgdGlsZS5cbiAgICAgICAgICAgIGNvb3JkID0gVGlsZUNvb3JkLmZyb21JRChpZHNbaV0pLFxuICAgICAgICAgICAgeiA9IGNvb3JkLnosXG4gICAgICAgICAgICB4ID0gY29vcmQueCxcbiAgICAgICAgICAgIHkgPSBjb29yZC55LFxuICAgICAgICAgICAgdyA9IGNvb3JkLnc7XG5cbiAgICAgICAgLy8gaWYgeiA+IG1heHpvb20gdGhlbiB0aGUgdGlsZSBpcyBhY3R1YWxseSBhIG92ZXJzY2FsZWQgbWF4em9vbSB0aWxlLFxuICAgICAgICAvLyBzbyBjYWxjdWxhdGUgdGhlIG1hdHJpeCB0aGUgbWF4em9vbSB0aWxlIHdvdWxkIHVzZS5cbiAgICAgICAgeiA9IE1hdGgubWluKHosIHRoaXMubWF4em9vbSk7XG5cbiAgICAgICAgeCArPSB3ICogKDEgPDwgeik7XG4gICAgICAgIHRpbGUuY2FsY3VsYXRlTWF0cmljZXMoeiwgeCwgeSwgcGFpbnRlci50cmFuc2Zvcm0sIHBhaW50ZXIpO1xuXG4gICAgICAgIHBhaW50ZXIuZHJhd1RpbGUodGlsZSwgbGF5ZXJzKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLl92ZWN0b3JGZWF0dXJlc0F0ID0gZnVuY3Rpb24oY29vcmQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuX3B5cmFtaWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBbXSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gdGhpcy5fcHlyYW1pZC50aWxlQXQoY29vcmQpO1xuICAgIGlmICghcmVzdWx0KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuXG4gICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3F1ZXJ5IGZlYXR1cmVzJywge1xuICAgICAgICB1aWQ6IHJlc3VsdC50aWxlLnVpZCxcbiAgICAgICAgeDogcmVzdWx0LngsXG4gICAgICAgIHk6IHJlc3VsdC55LFxuICAgICAgICBzY2FsZTogcmVzdWx0LnNjYWxlLFxuICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgfSwgY2FsbGJhY2ssIHJlc3VsdC50aWxlLndvcmtlcklEKTtcbn07XG5cbi8qXG4gKiBDcmVhdGUgYSB0aWxlZCBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50eXBlIEVpdGhlciBgcmFzdGVyYCBvciBgdmVjdG9yYC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCBBIHRpbGUgc291cmNlIFVSTC4gVGhpcyBzaG91bGQgZWl0aGVyIGJlIGBtYXBib3g6Ly97bWFwaWR9YCBvciBhIGZ1bGwgYGh0dHBbc11gIHVybCB0aGF0IHBvaW50cyB0byBhIFRpbGVKU09OIGVuZHBvaW50LlxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy50aWxlcyBBbiBhcnJheSBvZiB0aWxlIHNvdXJjZXMuIElmIGB1cmxgIGlzIG5vdCBzcGVjaWZpZWQsIGB0aWxlc2AgY2FuIGJlIHVzZWQgaW5zdGVhZCB0byBzcGVjaWZ5IHRpbGUgc291cmNlcywgYXMgaW4gdGhlIFRpbGVKU09OIHNwZWMuIE90aGVyIFRpbGVKU09OIGtleXMgc3VjaCBhcyBgbWluem9vbWAgYW5kIGBtYXh6b29tYCBjYW4gYmUgc3BlY2lmaWVkIGluIGEgc291cmNlIG9iamVjdCBpZiBgdGlsZXNgIGlzIHVzZWQuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5pZCBBbiBvcHRpb25hbCBgaWRgIHRvIGFzc2lnbiB0byB0aGUgc291cmNlXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGlsZVNpemU9NTEyXSBPcHRpb25hbCB0aWxlIHNpemUgKHdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzLCBhc3N1bWluZyB0aWxlcyBhcmUgc3F1YXJlKS4gVGhpcyBvcHRpb24gaXMgb25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBzb3VyY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5jYWNoZVNpemUgT3B0aW9uYWwgbWF4IG51bWJlciBvZiB0aWxlcyB0byBjYWNoZSBhdCBhbnkgZ2l2ZW4gdGltZVxuICogQGV4YW1wbGVcbiAqIHZhciBzb3VyY2VPYmogPSBuZXcgbWFwYm94Z2wuU291cmNlLmNyZWF0ZSh7XG4gKiAgICB0eXBlOiAndmVjdG9yJyxcbiAqICAgIHVybDogJ21hcGJveDovL21hcGJveC5tYXBib3gtc3RyZWV0cy12NSdcbiAqIH0pO1xuICogbWFwLmFkZFNvdXJjZSgnc29tZSBpZCcsIHNvdXJjZU9iaik7IC8vIGFkZFxuICogbWFwLnJlbW92ZVNvdXJjZSgnc29tZSBpZCcpOyAgLy8gcmVtb3ZlXG4gKi9cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24oc291cmNlKSB7XG4gICAgLy8gVGhpcyBpcyBub3QgYXQgZmlsZSBzY29wZSBpbiBvcmRlciB0byBhdm9pZCBhIGNpcmN1bGFyIHJlcXVpcmUuXG4gICAgdmFyIHNvdXJjZXMgPSB7XG4gICAgICAgIHZlY3RvcjogcmVxdWlyZSgnLi92ZWN0b3JfdGlsZV9zb3VyY2UnKSxcbiAgICAgICAgcmFzdGVyOiByZXF1aXJlKCcuL3Jhc3Rlcl90aWxlX3NvdXJjZScpLFxuICAgICAgICBnZW9qc29uOiByZXF1aXJlKCcuL2dlb2pzb25fc291cmNlJyksXG4gICAgICAgIHZpZGVvOiByZXF1aXJlKCcuL3ZpZGVvX3NvdXJjZScpXG4gICAgfTtcblxuICAgIGZvciAodmFyIHR5cGUgaW4gc291cmNlcykge1xuICAgICAgICBpZiAoc291cmNlIGluc3RhbmNlb2Ygc291cmNlc1t0eXBlXSkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgc291cmNlc1tzb3VyY2UudHlwZV0oc291cmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnbG1hdHJpeCA9IHJlcXVpcmUoJ2dsLW1hdHJpeCcpO1xudmFyIG1hdDIgPSBnbG1hdHJpeC5tYXQyO1xudmFyIG1hdDQgPSBnbG1hdHJpeC5tYXQ0O1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBCdWZmZXJTZXQgPSByZXF1aXJlKCcuLi9kYXRhL2J1ZmZlci9idWZmZXJfc2V0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZTtcblxuLyoqXG4gKiBBIHRpbGUgb2JqZWN0IGlzIHRoZSBjb21iaW5hdGlvbiBvZiBhIENvb3JkaW5hdGUsIHdoaWNoIGRlZmluZXNcbiAqIGl0cyBwbGFjZSwgYXMgd2VsbCBhcyBhIHVuaXF1ZSBJRCBhbmQgZGF0YSB0cmFja2luZyBmb3IgaXRzIGNvbnRlbnRcbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZVxuICovXG5mdW5jdGlvbiBUaWxlKGNvb3JkLCBzaXplKSB7XG4gICAgdGhpcy5jb29yZCA9IGNvb3JkO1xuICAgIHRoaXMudWlkID0gdXRpbC51bmlxdWVJZCgpO1xuICAgIHRoaXMubG9hZGVkID0gZmFsc2U7XG4gICAgdGhpcy51c2VzID0gMDtcbiAgICB0aGlzLnRpbGVTaXplID0gc2l6ZTtcbn1cblxuVGlsZS5wcm90b3R5cGUgPSB7XG4gICAgLy8gdG9kbyB1bmhhcmRjb2RlXG4gICAgdGlsZUV4dGVudDogNDA5NixcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgaW50ZXJuYWwgcG9zTWF0cml4IHRoYXQgdGhpcyB0aWxlIHVzZXMgdG8gZGlzcGxheVxuICAgICAqIGl0c2VsZiBpbiBhIG1hcCwgZ2l2ZW4gYSBjb29yZGluYXRlIGFzICh6LCB4LCB5KSBhbmQgYSB0cmFuc2Zvcm1cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gelxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICovXG4gICAgY2FsY3VsYXRlTWF0cmljZXM6IGZ1bmN0aW9uKHosIHgsIHksIHRyYW5zZm9ybSkge1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgbW9kZWwtdmlldyBtYXRyaXggdGhhdCBjb252ZXJ0cyBmcm9tIHRoZSB0aWxlIGNvb3JkaW5hdGVzXG4gICAgICAgIC8vIHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAgICAgICAgdmFyIHRpbGVTY2FsZSA9IE1hdGgucG93KDIsIHopO1xuICAgICAgICB2YXIgc2NhbGUgPSB0cmFuc2Zvcm0ud29ybGRTaXplIC8gdGlsZVNjYWxlO1xuXG4gICAgICAgIC8vIFRPRE86IHJlbW92ZVxuICAgICAgICB0aGlzLnNjYWxlID0gc2NhbGU7XG5cbiAgICAgICAgLy8gVGhlIHBvc2l0aW9uIG1hdHJpeFxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDY0QXJyYXkoMTYpO1xuICAgICAgICBtYXQ0LmlkZW50aXR5KHRoaXMucG9zTWF0cml4KTtcbiAgICAgICAgbWF0NC50cmFuc2xhdGUodGhpcy5wb3NNYXRyaXgsIHRoaXMucG9zTWF0cml4LCBbeCAqIHNjYWxlLCB5ICogc2NhbGUsIDBdKTtcblxuICAgICAgICBtYXQ0LnNjYWxlKHRoaXMucG9zTWF0cml4LCB0aGlzLnBvc01hdHJpeCwgWyBzY2FsZSAvIHRoaXMudGlsZUV4dGVudCwgc2NhbGUgLyB0aGlzLnRpbGVFeHRlbnQsIDEgXSk7XG4gICAgICAgIG1hdDQubXVsdGlwbHkodGhpcy5wb3NNYXRyaXgsIHRyYW5zZm9ybS5nZXRQcm9qTWF0cml4KCksIHRoaXMucG9zTWF0cml4KTtcblxuICAgICAgICAvLyBUaGUgZXh0cnVzaW9uIG1hdHJpeC5cbiAgICAgICAgdGhpcy5leE1hdHJpeCA9IG1hdDQuY3JlYXRlKCk7XG4gICAgICAgIG1hdDQub3J0aG8odGhpcy5leE1hdHJpeCwgMCwgdHJhbnNmb3JtLndpZHRoLCB0cmFuc2Zvcm0uaGVpZ2h0LCAwLCAwLCAtMSk7XG4gICAgICAgIC8vbWF0NC5yb3RhdGVaKHRoaXMuZXhNYXRyaXgsIHRoaXMuZXhNYXRyaXgsIC10cmFuc2Zvcm0uYW5nbGUpO1xuXG4gICAgICAgIC8vIDJ4MiBtYXRyaXggZm9yIHJvdGF0aW5nIHBvaW50c1xuICAgICAgICB0aGlzLnJvdGF0aW9uTWF0cml4ID0gbWF0Mi5jcmVhdGUoKTtcbiAgICAgICAgbWF0Mi5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCwgdGhpcy5yb3RhdGlvbk1hdHJpeCwgdHJhbnNmb3JtLmFuZ2xlKTtcblxuICAgICAgICB0aGlzLnBvc01hdHJpeCA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5wb3NNYXRyaXgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGNvb3JkaW5hdGUgcG9zaXRpb24sIHpvb20gdGhhdCBjb29yZGluYXRlIHRvIG15IHpvb20gYW5kXG4gICAgICogc2NhbGUgYW5kIHJldHVybiBhIHBvc2l0aW9uIGluIHgsIHksIHNjYWxlXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHBvc2l0aW9uXG4gICAgICovXG4gICAgcG9zaXRpb25BdDogZnVuY3Rpb24oY29vcmQsIHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgY29vcmQgPSBjb29yZC56b29tVG8oTWF0aC5taW4odGhpcy5jb29yZC56LCBzb3VyY2VNYXhab29tKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiAoY29vcmQuY29sdW1uIC0gdGhpcy5jb29yZC54KSAqIDQwOTYsXG4gICAgICAgICAgICB5OiAoY29vcmQucm93IC0gdGhpcy5jb29yZC55KSAqIDQwOTYsXG4gICAgICAgICAgICBzY2FsZTogdGhpcy5zY2FsZVxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHaXZlbiBhIGRhdGEgb2JqZWN0IHdpdGggYSAnYnVmZmVycycgcHJvcGVydHksIGxvYWQgaXQgaW50b1xuICAgICAqIHRoaXMgdGlsZSdzIGVsZW1lbnRHcm91cHMgYW5kIGJ1ZmZlcnMgcHJvcGVydGllcyBhbmQgc2V0IGxvYWRlZFxuICAgICAqIHRvIHRydWUuIElmIHRoZSBkYXRhIGlzIG51bGwsIGxpa2UgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHlcbiAgICAgKiBHZW9KU09OIHRpbGUsIG5vLW9wIGJ1dCBzdGlsbCBzZXQgbG9hZGVkIHRvIHRydWUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBlbXB0eSBHZW9KU09OIHRpbGVcbiAgICAgICAgaWYgKCFkYXRhKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXJzID0gbmV3IEJ1ZmZlclNldChkYXRhLmJ1ZmZlcnMpO1xuICAgICAgICB0aGlzLmVsZW1lbnRHcm91cHMgPSBkYXRhLmVsZW1lbnRHcm91cHM7XG4gICAgICAgIHRoaXMudGlsZUV4dGVudCA9IGRhdGEuZXh0ZW50O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBnaXZlbiBhIGRhdGEgb2JqZWN0IGFuZCBhIEdMIHBhaW50ZXIsIGRlc3Ryb3kgYW5kIHJlLWNyZWF0ZVxuICAgICAqIGFsbCBvZiBpdHMgYnVmZmVycy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyXG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICByZWxvYWRTeW1ib2xEYXRhOiBmdW5jdGlvbihkYXRhLCBwYWludGVyKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIC8vIHRoZSB0aWxlIGhhcyBiZWVuIGRlc3Ryb3llZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5nbHlwaEVsZW1lbnQuZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25WZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50LmRlc3Ryb3kocGFpbnRlci5nbCk7XG4gICAgICAgIHRoaXMuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXguZGVzdHJveShwYWludGVyLmdsKTtcblxuICAgICAgICB2YXIgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoZGF0YS5idWZmZXJzKTtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoVmVydGV4ID0gYnVmZmVycy5nbHlwaFZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmdseXBoRWxlbWVudCA9IGJ1ZmZlcnMuZ2x5cGhFbGVtZW50O1xuICAgICAgICB0aGlzLmJ1ZmZlcnMuaWNvblZlcnRleCA9IGJ1ZmZlcnMuaWNvblZlcnRleDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmljb25FbGVtZW50ID0gYnVmZmVycy5pY29uRWxlbWVudDtcbiAgICAgICAgdGhpcy5idWZmZXJzLmNvbGxpc2lvbkJveFZlcnRleCA9IGJ1ZmZlcnMuY29sbGlzaW9uQm94VmVydGV4O1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIGRhdGEuZWxlbWVudEdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50R3JvdXBzW2lkXSA9IGRhdGEuZWxlbWVudEdyb3Vwc1tpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWFrZSBzdXJlIHRoYXQgdGhpcyB0aWxlIGRvZXNuJ3Qgb3duIGFueSBkYXRhIHdpdGhpbiBhIGdpdmVuXG4gICAgICogcGFpbnRlciwgc28gdGhhdCBpdCBkb2Vzbid0IGNvbnN1bWUgYW55IG1lbW9yeSBvciBtYWludGFpblxuICAgICAqIGFueSByZWZlcmVuY2VzIHRvIHRoZSBwYWludGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYWludGVyIGdsIHBhaW50ZXIgb2JqZWN0XG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB1bmxvYWRWZWN0b3JEYXRhOiBmdW5jdGlvbihwYWludGVyKSB7XG4gICAgICAgIGZvciAodmFyIGIgaW4gdGhpcy5idWZmZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlcnNbYl0uZGVzdHJveShwYWludGVyLmdsKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSBudWxsO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gVGlsZUNvb3JkO1xuXG5mdW5jdGlvbiBUaWxlQ29vcmQoeiwgeCwgeSwgdykge1xuICAgIGlmICh3ID09PSB1bmRlZmluZWQpIHcgPSAwO1xuICAgIHRoaXMueiA9IHo7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMudyA9IHc7XG5cbiAgICAvLyBjYWxjdWxhdGUgaWRcbiAgICB3ICo9IDI7XG4gICAgaWYgKHcgPCAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB2YXIgZGltID0gMSA8PCB0aGlzLno7XG4gICAgdGhpcy5pZCA9ICgoZGltICogZGltICogdyArIGRpbSAqIHRoaXMueSArIHRoaXMueCkgKiAzMikgKyB0aGlzLno7XG59XG5cblRpbGVDb29yZC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy56ICsgXCIvXCIgKyB0aGlzLnggKyBcIi9cIiArIHRoaXMueTtcbn07XG5cbi8vIFBhcnNlIGEgcGFja2VkIGludGVnZXIgaWQgaW50byBhIFRpbGVDb29yZCBvYmplY3RcblRpbGVDb29yZC5mcm9tSUQgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciB6ID0gaWQgJSAzMiwgZGltID0gMSA8PCB6O1xuICAgIHZhciB4eSA9ICgoaWQgLSB6KSAvIDMyKTtcbiAgICB2YXIgeCA9IHh5ICUgZGltLCB5ID0gKCh4eSAtIHgpIC8gZGltKSAlIGRpbTtcbiAgICB2YXIgdyA9IE1hdGguZmxvb3IoeHkgLyAoZGltICogZGltKSk7XG4gICAgaWYgKHcgJSAyICE9PSAwKSB3ID0gdyAqIC0xIC0gMTtcbiAgICB3IC89IDI7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQoeiwgeCwgeSwgdyk7XG59O1xuXG4vLyBnaXZlbiBhIGxpc3Qgb2YgdXJscywgY2hvb3NlIGEgdXJsIHRlbXBsYXRlIGFuZCByZXR1cm4gYSB0aWxlIFVSTFxuVGlsZUNvb3JkLnByb3RvdHlwZS51cmwgPSBmdW5jdGlvbih1cmxzLCBzb3VyY2VNYXhab29tKSB7XG4gICAgcmV0dXJuIHVybHNbKHRoaXMueCArIHRoaXMueSkgJSB1cmxzLmxlbmd0aF1cbiAgICAgICAgLnJlcGxhY2UoJ3twcmVmaXh9JywgKHRoaXMueCAlIDE2KS50b1N0cmluZygxNikgKyAodGhpcy55ICUgMTYpLnRvU3RyaW5nKDE2KSlcbiAgICAgICAgLnJlcGxhY2UoJ3t6fScsIE1hdGgubWluKHRoaXMueiwgc291cmNlTWF4Wm9vbSB8fCB0aGlzLnopKVxuICAgICAgICAucmVwbGFjZSgne3h9JywgdGhpcy54KVxuICAgICAgICAucmVwbGFjZSgne3l9JywgdGhpcy55KTtcbn07XG5cbi8vIFJldHVybiB0aGUgY29vcmRpbmF0ZSBvZiB0aGUgcGFyZW50IHRpbGVcblRpbGVDb29yZC5wcm90b3R5cGUucGFyZW50ID0gZnVuY3Rpb24oc291cmNlTWF4Wm9vbSkge1xuICAgIGlmICh0aGlzLnogPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgLy8gdGhlIGlkIHJlcHJlc2VudHMgYW4gb3ZlcnNjYWxlZCB0aWxlLCByZXR1cm4gdGhlIHNhbWUgY29vcmRpbmF0ZXMgd2l0aCBhIGxvd2VyIHpcbiAgICBpZiAodGhpcy56ID4gc291cmNlTWF4Wm9vbSkge1xuICAgICAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRpbGVDb29yZCh0aGlzLnogLSAxLCBNYXRoLmZsb29yKHRoaXMueCAvIDIpLCBNYXRoLmZsb29yKHRoaXMueSAvIDIpLCB0aGlzLncpO1xufTtcblxuVGlsZUNvb3JkLnByb3RvdHlwZS53cmFwcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBUaWxlQ29vcmQodGhpcy56LCB0aGlzLngsIHRoaXMueSwgMCk7XG59O1xuXG4vLyBSZXR1cm4gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB0aWxlJ3MgY2hpbGRyZW5cblRpbGVDb29yZC5wcm90b3R5cGUuY2hpbGRyZW4gPSBmdW5jdGlvbihzb3VyY2VNYXhab29tKSB7XG5cbiAgICBpZiAodGhpcy56ID49IHNvdXJjZU1heFpvb20pIHtcbiAgICAgICAgLy8gcmV0dXJuIGEgc2luZ2xlIHRpbGUgY29vcmQgcmVwcmVzZW50aW5nIGEgYW4gb3ZlcnNjYWxlZCB0aWxlXG4gICAgICAgIHJldHVybiBbbmV3IFRpbGVDb29yZCh0aGlzLnogKyAxLCB0aGlzLngsIHRoaXMueSwgdGhpcy53KV07XG4gICAgfVxuXG4gICAgdmFyIHogPSB0aGlzLnogKyAxO1xuICAgIHZhciB4ID0gdGhpcy54ICogMjtcbiAgICB2YXIgeSA9IHRoaXMueSAqIDI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IFRpbGVDb29yZCh6LCB4LCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5LCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHgsIHkgKyAxLCB0aGlzLncpLFxuICAgICAgICBuZXcgVGlsZUNvb3JkKHosIHggKyAxLCB5ICsgMSwgdGhpcy53KVxuICAgIF07XG59O1xuXG4vLyBUYWtlbiBmcm9tIHBvbHltYXBzIHNyYy9MYXllci5qc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3NpbXBsZWdlby9wb2x5bWFwcy9ibG9iL21hc3Rlci9zcmMvTGF5ZXIuanMjTDMzMy1MMzgzXG5cbmZ1bmN0aW9uIGVkZ2UoYSwgYikge1xuICAgIGlmIChhLnJvdyA+IGIucm93KSB7IHZhciB0ID0gYTsgYSA9IGI7IGIgPSB0OyB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDA6IGEuY29sdW1uLFxuICAgICAgICB5MDogYS5yb3csXG4gICAgICAgIHgxOiBiLmNvbHVtbixcbiAgICAgICAgeTE6IGIucm93LFxuICAgICAgICBkeDogYi5jb2x1bW4gLSBhLmNvbHVtbixcbiAgICAgICAgZHk6IGIucm93IC0gYS5yb3dcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBzY2FuU3BhbnMoZTAsIGUxLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciB5MCA9IE1hdGgubWF4KHltaW4sIE1hdGguZmxvb3IoZTEueTApKTtcbiAgICB2YXIgeTEgPSBNYXRoLm1pbih5bWF4LCBNYXRoLmNlaWwoZTEueTEpKTtcblxuICAgIC8vIHNvcnQgZWRnZXMgYnkgeC1jb29yZGluYXRlXG4gICAgaWYgKChlMC54MCA9PT0gZTEueDAgJiYgZTAueTAgPT09IGUxLnkwKSA/XG4gICAgICAgICAgICAoZTAueDAgKyBlMS5keSAvIGUwLmR5ICogZTAuZHggPCBlMS54MSkgOlxuICAgICAgICAgICAgKGUwLngxIC0gZTEuZHkgLyBlMC5keSAqIGUwLmR4IDwgZTEueDApKSB7XG4gICAgICAgIHZhciB0ID0gZTA7IGUwID0gZTE7IGUxID0gdDtcbiAgICB9XG5cbiAgICAvLyBzY2FuIGxpbmVzIVxuICAgIHZhciBtMCA9IGUwLmR4IC8gZTAuZHk7XG4gICAgdmFyIG0xID0gZTEuZHggLyBlMS5keTtcbiAgICB2YXIgZDAgPSBlMC5keCA+IDA7IC8vIHVzZSB5ICsgMSB0byBjb21wdXRlIHgwXG4gICAgdmFyIGQxID0gZTEuZHggPCAwOyAvLyB1c2UgeSArIDEgdG8gY29tcHV0ZSB4MVxuICAgIGZvciAodmFyIHkgPSB5MDsgeSA8IHkxOyB5KyspIHtcbiAgICAgICAgdmFyIHgwID0gbTAgKiBNYXRoLm1heCgwLCBNYXRoLm1pbihlMC5keSwgeSArIGQwIC0gZTAueTApKSArIGUwLngwO1xuICAgICAgICB2YXIgeDEgPSBtMSAqIE1hdGgubWF4KDAsIE1hdGgubWluKGUxLmR5LCB5ICsgZDEgLSBlMS55MCkpICsgZTEueDA7XG4gICAgICAgIHNjYW5MaW5lKE1hdGguZmxvb3IoeDEpLCBNYXRoLmNlaWwoeDApLCB5KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNjYW5UcmlhbmdsZShhLCBiLCBjLCB5bWluLCB5bWF4LCBzY2FuTGluZSkge1xuICAgIHZhciBhYiA9IGVkZ2UoYSwgYiksXG4gICAgICAgIGJjID0gZWRnZShiLCBjKSxcbiAgICAgICAgY2EgPSBlZGdlKGMsIGEpO1xuXG4gICAgdmFyIHQ7XG5cbiAgICAvLyBzb3J0IGVkZ2VzIGJ5IHktbGVuZ3RoXG4gICAgaWYgKGFiLmR5ID4gYmMuZHkpIHsgdCA9IGFiOyBhYiA9IGJjOyBiYyA9IHQ7IH1cbiAgICBpZiAoYWIuZHkgPiBjYS5keSkgeyB0ID0gYWI7IGFiID0gY2E7IGNhID0gdDsgfVxuICAgIGlmIChiYy5keSA+IGNhLmR5KSB7IHQgPSBiYzsgYmMgPSBjYTsgY2EgPSB0OyB9XG5cbiAgICAvLyBzY2FuIHNwYW4hIHNjYW4gc3BhbiFcbiAgICBpZiAoYWIuZHkpIHNjYW5TcGFucyhjYSwgYWIsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbiAgICBpZiAoYmMuZHkpIHNjYW5TcGFucyhjYSwgYmMsIHltaW4sIHltYXgsIHNjYW5MaW5lKTtcbn1cblxuVGlsZUNvb3JkLmNvdmVyID0gZnVuY3Rpb24oeiwgYm91bmRzLCBhY3R1YWxaKSB7XG4gICAgdmFyIHRpbGVzID0gMSA8PCB6O1xuICAgIHZhciB0ID0ge307XG5cbiAgICBmdW5jdGlvbiBzY2FuTGluZSh4MCwgeDEsIHkpIHtcbiAgICAgICAgdmFyIHgsIHd4O1xuICAgICAgICBpZiAoeSA+PSAwICYmIHkgPD0gdGlsZXMpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IHgwOyB4IDwgeDE7IHgrKykge1xuICAgICAgICAgICAgICAgIHd4ID0gKHggKyB0aWxlcykgJSB0aWxlcztcbiAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBuZXcgVGlsZUNvb3JkKGFjdHVhbFosIHd4LCB5LCBNYXRoLmZsb29yKHggLyB0aWxlcykpO1xuICAgICAgICAgICAgICAgIHRbY29vcmQuaWRdID0gY29vcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXZpZGUgdGhlIHNjcmVlbiB1cCBpbiB0d28gdHJpYW5nbGVzIGFuZCBzY2FuIGVhY2ggb2YgdGhlbTpcbiAgICAvLyArLS0tL1xuICAgIC8vIHwgLyB8XG4gICAgLy8gLy0tLStcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzBdLCBib3VuZHNbMV0sIGJvdW5kc1syXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcbiAgICBzY2FuVHJpYW5nbGUoYm91bmRzWzJdLCBib3VuZHNbM10sIGJvdW5kc1swXSwgMCwgdGlsZXMsIHNjYW5MaW5lKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0KS5tYXAoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRbaWRdO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFRpbGUgPSByZXF1aXJlKCcuL3RpbGUnKTtcbnZhciBUaWxlQ29vcmQgPSByZXF1aXJlKCcuL3RpbGVfY29vcmQnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQ2FjaGUgPSByZXF1aXJlKCcuLi91dGlsL21ydV9jYWNoZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBUaWxlUHlyYW1pZDtcblxuLyoqXG4gKiBBIHRpbGUgcHlyYW1pZCBpcyBhIHNwZWNpYWxpemVkIGNhY2hlIGFuZCBkYXRhc3RydWN0dXJlXG4gKiB0aGF0IGNvbnRhaW5zIHRpbGVzLiBJdCdzIHVzZWQgYnkgc291cmNlcyB0byBtYW5hZ2UgdGhlaXJcbiAqIGRhdGEuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnRpbGVTaXplXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5taW56b29tXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5tYXh6b29tXG4gKi9cbmZ1bmN0aW9uIFRpbGVQeXJhbWlkKG9wdGlvbnMpIHtcbiAgICB0aGlzLnRpbGVTaXplID0gb3B0aW9ucy50aWxlU2l6ZTtcbiAgICB0aGlzLm1pbnpvb20gPSBvcHRpb25zLm1pbnpvb207XG4gICAgdGhpcy5tYXh6b29tID0gb3B0aW9ucy5tYXh6b29tO1xuICAgIHRoaXMucmVwYXJzZU92ZXJzY2FsZWQgPSBvcHRpb25zLnJlcGFyc2VPdmVyc2NhbGVkO1xuXG4gICAgdGhpcy5fbG9hZCA9IG9wdGlvbnMubG9hZDtcbiAgICB0aGlzLl9hYm9ydCA9IG9wdGlvbnMuYWJvcnQ7XG4gICAgdGhpcy5fdW5sb2FkID0gb3B0aW9ucy51bmxvYWQ7XG4gICAgdGhpcy5fYWRkID0gb3B0aW9ucy5hZGQ7XG4gICAgdGhpcy5fcmVtb3ZlID0gb3B0aW9ucy5yZW1vdmU7XG4gICAgdGhpcy5fcmVkb1BsYWNlbWVudCA9IG9wdGlvbnMucmVkb1BsYWNlbWVudDtcblxuICAgIHRoaXMuX3RpbGVzID0ge307XG4gICAgdGhpcy5fY2FjaGUgPSBuZXcgQ2FjaGUob3B0aW9ucy5jYWNoZVNpemUsIGZ1bmN0aW9uKHRpbGUpIHsgcmV0dXJuIHRoaXMuX3VubG9hZCh0aWxlKTsgfS5iaW5kKHRoaXMpKTtcbn1cblxuVGlsZVB5cmFtaWQucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIENvbmZpcm0gdGhhdCBldmVyeSB0cmFja2VkIHRpbGUgaXMgbG9hZGVkLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIGFsbCB0aWxlcyBhcmUgbG9hZGVkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgdCBpbiB0aGlzLl90aWxlcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl90aWxlc1t0XS5sb2FkZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRpbGUgaWRzIG9yZGVyZWQgd2l0aCB6LW9yZGVyLCBhbmQgY2FzdCB0byBudW1iZXJzXG4gICAgICogQHJldHVybnMge0FycmF5PG51bWJlcj59IGlkc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgb3JkZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl90aWxlcylcbiAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIChiICUgMzIpIC0gKGEgJSAzMik7IH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKGlkKSB7IHJldHVybiAraWQ7IH0pO1xuICAgIH0sXG5cbiAgICByZW5kZXJlZElEczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yZGVyZWRJRHMoKS5maWx0ZXIoZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90aWxlc1tpZF0ubG9hZGVkICYmICF0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICByZWxvYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9jYWNoZS5yZXNldCgpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMuX3RpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2FkKHRoaXMuX3RpbGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzcGVjaWZpYyB0aWxlIGJ5IGlkXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCB0aWxlIGlkXG4gICAgICogQHJldHVybnMge09iamVjdH0gdGlsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0VGlsZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RpbGVzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogZ2V0IHRoZSB6b29tIGxldmVsIGFkanVzdGVkIGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtYXAgYW5kIHNvdXJjZSB0aWxlc2l6ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtXG4gICAgICogQHJldHVybnMge251bWJlcn0gem9vbSBsZXZlbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm0uem9vbSArIE1hdGgubG9nKHRyYW5zZm9ybS50aWxlU2l6ZSAvIHRoaXMudGlsZVNpemUpIC8gTWF0aC5MTjI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHpvb20gbGV2ZWwgdGhhdCB3aWxsIGNvdmVyIGFsbCB0aWxlcyBpbiBhIGdpdmVuIHRyYW5zZm9ybVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSB6b29tIGxldmVsXG4gICAgICovXG4gICAgY292ZXJpbmdab29tTGV2ZWw6IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldFpvb20odHJhbnNmb3JtKSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgdHJhbnNmb3JtLCByZXR1cm4gYWxsIGNvb3JkaW5hdGVzIHRoYXQgY291bGQgY292ZXIgdGhhdFxuICAgICAqIHRyYW5zZm9ybSBmb3IgYSBjb3ZlcmluZyB6b29tIGxldmVsLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0cmFuc2Zvcm1cbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8VGlsZT59IHRpbGVzXG4gICAgICovXG4gICAgY292ZXJpbmdUaWxlczogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIHZhciB6ID0gdGhpcy5jb3ZlcmluZ1pvb21MZXZlbCh0cmFuc2Zvcm0pO1xuICAgICAgICB2YXIgYWN0dWFsWiA9IHo7XG5cbiAgICAgICAgaWYgKHogPCB0aGlzLm1pbnpvb20pIHJldHVybiBbXTtcbiAgICAgICAgaWYgKHogPiB0aGlzLm1heHpvb20pIHogPSB0aGlzLm1heHpvb207XG5cbiAgICAgICAgdmFyIHRyID0gdHJhbnNmb3JtLFxuICAgICAgICAgICAgdGlsZUNlbnRlciA9IHRyLmxvY2F0aW9uQ29vcmRpbmF0ZSh0ci5jZW50ZXIpLl96b29tVG8oeiksXG4gICAgICAgICAgICBjZW50ZXJQb2ludCA9IG5ldyBQb2ludCh0aWxlQ2VudGVyLmNvbHVtbiAtIDAuNSwgdGlsZUNlbnRlci5yb3cgLSAwLjUpO1xuXG4gICAgICAgIHJldHVybiBUaWxlQ29vcmQuY292ZXIoeiwgW1xuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCgwLCAwKSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQodHIud2lkdGgsIDApKS5fem9vbVRvKHopLFxuICAgICAgICAgICAgdHIucG9pbnRDb29yZGluYXRlKG5ldyBQb2ludCh0ci53aWR0aCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KSxcbiAgICAgICAgICAgIHRyLnBvaW50Q29vcmRpbmF0ZShuZXcgUG9pbnQoMCwgdHIuaGVpZ2h0KSkuX3pvb21Ubyh6KVxuICAgICAgICBdLCB0aGlzLnJlcGFyc2VPdmVyc2NhbGVkID8gYWN0dWFsWiA6IHopLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGNlbnRlclBvaW50LmRpc3QoYSkgLSBjZW50ZXJQb2ludC5kaXN0KGIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmluZCBjaGlsZHJlbiBvZiB0aGUgZ2l2ZW4gdGlsZSAodXAgdG8gbWF4Q292ZXJpbmdab29tKSB0aGF0IGFyZSBhbHJlYWR5IGxvYWRlZDtcbiAgICAgKiBhZGRzIGZvdW5kIHRpbGVzIHRvIHJldGFpbiBvYmplY3Q7IHJldHVybnMgdHJ1ZSBpZiBjaGlsZHJlbiBjb21wbGV0ZWx5IGNvdmVyIHRoZSB0aWxlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENvdmVyaW5nWm9vbVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0YWluXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIG9wZXJhdGlvbiB3YXMgY29tcGxldGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRDaGlsZHJlbjogZnVuY3Rpb24oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSB7XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IHRydWU7XG4gICAgICAgIHZhciB6ID0gY29vcmQuejtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGNvb3JkLmNoaWxkcmVuKHRoaXMubWF4em9vbSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaWQgPSBjb29yZHNbaV0uaWQ7XG4gICAgICAgICAgICBpZiAodGhpcy5fdGlsZXNbaWRdICYmIHRoaXMuX3RpbGVzW2lkXS5sb2FkZWQpIHtcbiAgICAgICAgICAgICAgICByZXRhaW5baWRdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29tcGxldGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoeiA8IG1heENvdmVyaW5nWm9vbSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBHbyBmdXJ0aGVyIGRvd24gdGhlIGhpZXJhcmNoeSB0byBmaW5kIG1vcmUgdW5sb2FkZWQgY2hpbGRyZW4uXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3Jkc1tpXSwgbWF4Q292ZXJpbmdab29tLCByZXRhaW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcGxldGU7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBsb2FkZWQgcGFyZW50IG9mIHRoZSBnaXZlbiB0aWxlICh1cCB0byBtaW5Db3ZlcmluZ1pvb20pO1xuICAgICAqIGFkZHMgdGhlIGZvdW5kIHRpbGUgdG8gcmV0YWluIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgdGlsZSBpZiBmb3VuZFxuICAgICAqXG4gICAgICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5Db3ZlcmluZ1pvb21cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJldGFpblxuICAgICAqIEByZXR1cm5zIHtUaWxlfSB0aWxlIG9iamVjdFxuICAgICAqL1xuICAgIGZpbmRMb2FkZWRQYXJlbnQ6IGZ1bmN0aW9uKGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbikge1xuICAgICAgICBmb3IgKHZhciB6ID0gY29vcmQueiAtIDE7IHogPj0gbWluQ292ZXJpbmdab29tOyB6LS0pIHtcbiAgICAgICAgICAgIGNvb3JkID0gY29vcmQucGFyZW50KHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2Nvb3JkLmlkXTtcbiAgICAgICAgICAgIGlmICh0aWxlICYmIHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0YWluW2Nvb3JkLmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aWxlcyB0aGF0IGFyZSBvdXRzaWRlIHRoZSB2aWV3cG9ydCBhbmQgYWRkcyBuZXcgdGlsZXMgdGhhdFxuICAgICAqIGFyZSBpbnNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXNlZCwgdHJhbnNmb3JtLCBmYWRlRHVyYXRpb24pIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBjb29yZDtcbiAgICAgICAgdmFyIHRpbGU7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBvdmVyem9vbWluZy91bmRlcnpvb21pbmcgYW1vdW50cy5cbiAgICAgICAgdmFyIHpvb20gPSBNYXRoLmZsb29yKHRoaXMuZ2V0Wm9vbSh0cmFuc2Zvcm0pKTtcbiAgICAgICAgdmFyIG1pbkNvdmVyaW5nWm9vbSA9IHV0aWwuY2xhbXAoem9vbSAtIDEwLCB0aGlzLm1pbnpvb20sIHRoaXMubWF4em9vbSk7XG4gICAgICAgIHZhciBtYXhDb3ZlcmluZ1pvb20gPSB1dGlsLmNsYW1wKHpvb20gKyAxLCAgdGhpcy5taW56b29tLCB0aGlzLm1heHpvb20pO1xuXG4gICAgICAgIC8vIFJldGFpbiBpcyBhIGxpc3Qgb2YgdGlsZXMgdGhhdCB3ZSBzaG91bGRuJ3QgZGVsZXRlLCBldmVuIGlmIHRoZXkgYXJlIG5vdFxuICAgICAgICAvLyB0aGUgbW9zdCBpZGVhbCB0aWxlIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydC4gVGhpcyBtYXkgaW5jbHVkZSB0aWxlcyBsaWtlXG4gICAgICAgIC8vIHBhcmVudCBvciBjaGlsZCB0aWxlcyB0aGF0IGFyZSAqYWxyZWFkeSogbG9hZGVkLlxuICAgICAgICB2YXIgcmV0YWluID0ge307XG4gICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICAvLyBDb3ZlcmVkIGlzIGEgbGlzdCBvZiByZXRhaW5lZCB0aWxlcyB3aG8ncyBhcmVhcyBhcmUgZnVsbCBjb3ZlcmVkIGJ5IG90aGVyLFxuICAgICAgICAvLyBiZXR0ZXIsIHJldGFpbmVkIHRpbGVzLiBUaGV5IGFyZSBub3QgZHJhd24gc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fY292ZXJlZFRpbGVzID0ge307XG5cbiAgICAgICAgdmFyIHJlcXVpcmVkID0gdXNlZCA/IHRoaXMuY292ZXJpbmdUaWxlcyh0cmFuc2Zvcm0pIDogW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXF1aXJlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29vcmQgPSByZXF1aXJlZFtpXTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmFkZFRpbGUoY29vcmQpO1xuXG4gICAgICAgICAgICByZXRhaW5bY29vcmQuaWRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHRpbGUubG9hZGVkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyBUaGUgdGlsZSB3ZSByZXF1aXJlIGlzIG5vdCB5ZXQgbG9hZGVkLlxuICAgICAgICAgICAgLy8gUmV0YWluIGNoaWxkIG9yIHBhcmVudCB0aWxlcyB0aGF0IGNvdmVyIHRoZSBzYW1lIGFyZWEuXG4gICAgICAgICAgICBpZiAoIXRoaXMuZmluZExvYWRlZENoaWxkcmVuKGNvb3JkLCBtYXhDb3ZlcmluZ1pvb20sIHJldGFpbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmRMb2FkZWRQYXJlbnQoY29vcmQsIG1pbkNvdmVyaW5nWm9vbSwgcmV0YWluKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHJldGFpbikge1xuICAgICAgICAgICAgY29vcmQgPSBUaWxlQ29vcmQuZnJvbUlEKGlkKTtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1tpZF07XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aWxlLnRpbWVBZGRlZCA+IG5vdyAtIChmYWRlRHVyYXRpb24gfHwgMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHRpbGUgaXMgc3RpbGwgZmFkaW5nIGluLiBGaW5kIHRpbGVzIHRvIGNyb3NzLWZhZGUgd2l0aCBpdC5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5maW5kTG9hZGVkQ2hpbGRyZW4oY29vcmQsIG1heENvdmVyaW5nWm9vbSwgcmV0YWluKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb3ZlcmVkVGlsZXNbaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0YWluW2lkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5kTG9hZGVkUGFyZW50KGNvb3JkLCBtaW5Db3ZlcmluZ1pvb20sIHJldGFpbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0aWxlcyB3ZSBkb24ndCBuZWVkIGFueW1vcmUuXG4gICAgICAgIHZhciByZW1vdmUgPSB1dGlsLmtleXNEaWZmZXJlbmNlKHRoaXMuX3RpbGVzLCByZXRhaW4pO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVRpbGUoK3JlbW92ZVtpXSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgdGlsZSwgZ2l2ZW4gaXRzIGNvb3JkaW5hdGUsIHRvIHRoZSBweXJhbWlkLlxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7Q29vcmRpbmF0ZX0gdGhlIGNvb3JkaW5hdGUuXG4gICAgICovXG4gICAgYWRkVGlsZTogZnVuY3Rpb24oY29vcmQpIHtcbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl90aWxlc1tjb29yZC5pZF07XG4gICAgICAgIGlmICh0aWxlKVxuICAgICAgICAgICAgcmV0dXJuIHRpbGU7XG5cbiAgICAgICAgdmFyIHdyYXBwZWQgPSBjb29yZC53cmFwcGVkKCk7XG4gICAgICAgIHRpbGUgPSB0aGlzLl90aWxlc1t3cmFwcGVkLmlkXTtcblxuICAgICAgICBpZiAoIXRpbGUpIHtcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLl9jYWNoZS5nZXQod3JhcHBlZC5pZCk7XG4gICAgICAgICAgICBpZiAodGlsZSAmJiB0aGlzLl9yZWRvUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVkb1BsYWNlbWVudCh0aWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGlsZSkge1xuICAgICAgICAgICAgdmFyIHpvb20gPSBjb29yZC56O1xuICAgICAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gem9vbSA+IHRoaXMubWF4em9vbSA/IE1hdGgucG93KDIsIHpvb20gLSB0aGlzLm1heHpvb20pIDogMTtcbiAgICAgICAgICAgIHRpbGUgPSBuZXcgVGlsZSh3cmFwcGVkLCB0aGlzLnRpbGVTaXplICogb3ZlcnNjYWxpbmcpO1xuICAgICAgICAgICAgdGhpcy5fbG9hZCh0aWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbGUudXNlcysrO1xuICAgICAgICB0aGlzLl90aWxlc1tjb29yZC5pZF0gPSB0aWxlO1xuICAgICAgICB0aGlzLl9hZGQodGlsZSwgY29vcmQpO1xuXG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSB0aWxlLCBnaXZlbiBpdHMgaWQsIGZyb20gdGhlIHB5cmFtaWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIHRpbGUgaWRcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBub3RoaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICByZW1vdmVUaWxlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2lkXTtcbiAgICAgICAgaWYgKCF0aWxlKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRpbGUudXNlcy0tO1xuICAgICAgICBkZWxldGUgdGhpcy5fdGlsZXNbaWRdO1xuICAgICAgICB0aGlzLl9yZW1vdmUodGlsZSk7XG5cbiAgICAgICAgaWYgKHRpbGUudXNlcyA+IDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHRpbGUubG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZS5hZGQodGlsZS5jb29yZC53cmFwcGVkKCkuaWQsIHRpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fYWJvcnQodGlsZSk7XG4gICAgICAgICAgICB0aGlzLl91bmxvYWQodGlsZSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCB0aWxlcyBmcm9tIHRoaXMgcHlyYW1pZFxuICAgICAqL1xuICAgIGNsZWFyVGlsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBpZCBpbiB0aGlzLl90aWxlcylcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlVGlsZShpZCk7XG4gICAgICAgIHRoaXMuX2NhY2hlLnJlc2V0KCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEZvciBhIGdpdmVuIGNvb3JkaW5hdGUsIHNlYXJjaCB0aHJvdWdoIG91ciBjdXJyZW50IHRpbGVzIGFuZCBhdHRlbXB0XG4gICAgICogdG8gZmluZCBhIHRpbGUgYXQgdGhhdCBwb2ludFxuICAgICAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSB0aWxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aWxlQXQ6IGZ1bmN0aW9uKGNvb3JkKSB7XG4gICAgICAgIHZhciBpZHMgPSB0aGlzLm9yZGVyZWRJRHMoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gdGhpcy5fdGlsZXNbaWRzW2ldXTtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aWxlLnBvc2l0aW9uQXQoY29vcmQsIHRoaXMubWF4em9vbSk7XG4gICAgICAgICAgICBpZiAocG9zICYmIHBvcy54ID49IDAgJiYgcG9zLnggPCA0MDk2ICYmIHBvcy55ID49IDAgJiYgcG9zLnkgPCA0MDk2KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGNsaWNrIGlzIHdpdGhpbiB0aGUgdmlld3BvcnQuIFRoZXJlIGlzIG9ubHkgZXZlciBvbmUgdGlsZSBpblxuICAgICAgICAgICAgICAgIC8vIGEgbGF5ZXIgdGhhdCBoYXMgdGhpcyBwcm9wZXJ0eS5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB0aWxlOiB0aWxlLFxuICAgICAgICAgICAgICAgICAgICB4OiBwb3MueCxcbiAgICAgICAgICAgICAgICAgICAgeTogcG9zLnksXG4gICAgICAgICAgICAgICAgICAgIHNjYWxlOiBwb3Muc2NhbGVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgU291cmNlID0gcmVxdWlyZSgnLi9zb3VyY2UnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlU291cmNlO1xuXG5mdW5jdGlvbiBWZWN0b3JUaWxlU291cmNlKG9wdGlvbnMpIHtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLCB1dGlsLnBpY2sob3B0aW9ucywgWyd1cmwnLCAndGlsZVNpemUnXSkpO1xuXG4gICAgaWYgKHRoaXMudGlsZVNpemUgIT09IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyJyk7XG4gICAgfVxuXG4gICAgU291cmNlLl9sb2FkVGlsZUpTT04uY2FsbCh0aGlzLCBvcHRpb25zKTtcbn1cblxuVmVjdG9yVGlsZVNvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIG1pbnpvb206IDAsXG4gICAgbWF4em9vbTogMjIsXG4gICAgdGlsZVNpemU6IDUxMixcbiAgICByZXBhcnNlT3ZlcnNjYWxlZDogdHJ1ZSxcbiAgICBfbG9hZGVkOiBmYWxzZSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5tYXAgPSBtYXA7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9weXJhbWlkICYmIHRoaXMuX3B5cmFtaWQubG9hZGVkKCk7XG4gICAgfSxcblxuICAgIHVwZGF0ZTogZnVuY3Rpb24odHJhbnNmb3JtKSB7XG4gICAgICAgIGlmICh0aGlzLl9weXJhbWlkKSB7XG4gICAgICAgICAgICB0aGlzLl9weXJhbWlkLnVwZGF0ZSh0aGlzLnVzZWQsIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVsb2FkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fcHlyYW1pZC5yZWxvYWQoKTtcbiAgICB9LFxuXG4gICAgcmVkb1BsYWNlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fcHlyYW1pZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlkcyA9IHRoaXMuX3B5cmFtaWQub3JkZXJlZElEcygpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRpbGUgPSB0aGlzLl9weXJhbWlkLmdldFRpbGUoaWRzW2ldKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHJlbmRlcjogU291cmNlLl9yZW5kZXJUaWxlcyxcbiAgICBmZWF0dXJlc0F0OiBTb3VyY2UuX3ZlY3RvckZlYXR1cmVzQXQsXG5cbiAgICBfbG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdmFyIG92ZXJzY2FsaW5nID0gdGlsZS5jb29yZC56ID4gdGhpcy5tYXh6b29tID8gTWF0aC5wb3coMiwgdGlsZS5jb29yZC56IC0gdGhpcy5tYXh6b29tKSA6IDE7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICB1cmw6IHRpbGUuY29vcmQudXJsKHRoaXMudGlsZXMsIHRoaXMubWF4em9vbSksXG4gICAgICAgICAgICB1aWQ6IHRpbGUudWlkLFxuICAgICAgICAgICAgY29vcmQ6IHRpbGUuY29vcmQsXG4gICAgICAgICAgICB6b29tOiB0aWxlLmNvb3JkLnosXG4gICAgICAgICAgICBtYXhab29tOiB0aGlzLm1heHpvb20sXG4gICAgICAgICAgICB0aWxlU2l6ZTogdGhpcy50aWxlU2l6ZSAqIG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgc291cmNlOiB0aGlzLmlkLFxuICAgICAgICAgICAgb3ZlcnNjYWxpbmc6IG92ZXJzY2FsaW5nLFxuICAgICAgICAgICAgYW5nbGU6IHRoaXMubWFwLnRyYW5zZm9ybS5hbmdsZSxcbiAgICAgICAgICAgIHBpdGNoOiB0aGlzLm1hcC50cmFuc2Zvcm0ucGl0Y2gsXG4gICAgICAgICAgICBjb2xsaXNpb25EZWJ1ZzogdGhpcy5tYXAuY29sbGlzaW9uRGVidWdcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGlsZS53b3JrZXJJRCkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbG9hZCB0aWxlJywgcGFyYW1zLCB0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcywgdGlsZSksIHRpbGUud29ya2VySUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGlsZS53b3JrZXJJRCA9IHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdsb2FkIHRpbGUnLCBwYXJhbXMsIHRoaXMuX3RpbGVMb2FkZWQuYmluZCh0aGlzLCB0aWxlKSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX3RpbGVMb2FkZWQ6IGZ1bmN0aW9uKHRpbGUsIGVyciwgZGF0YSkge1xuICAgICAgICBpZiAodGlsZS5hYm9ydGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgndGlsZS5lcnJvcicsIHt0aWxlOiB0aWxlfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLmxvYWRWZWN0b3JEYXRhKGRhdGEpO1xuXG4gICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgdGlsZS5yZWRvV2hlbkRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfYWJvcnRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRpbGUuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdhYm9ydCB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9hZGRUaWxlOiBmdW5jdGlvbih0aWxlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgndGlsZS5hZGQnLCB7dGlsZTogdGlsZX0pO1xuICAgIH0sXG5cbiAgICBfcmVtb3ZlVGlsZTogZnVuY3Rpb24odGlsZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3RpbGUucmVtb3ZlJywge3RpbGU6IHRpbGV9KTtcbiAgICB9LFxuXG4gICAgX3VubG9hZFRpbGU6IGZ1bmN0aW9uKHRpbGUpIHtcbiAgICAgICAgdGlsZS51bmxvYWRWZWN0b3JEYXRhKHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICB0aGlzLmdseXBoQXRsYXMucmVtb3ZlR2x5cGhzKHRpbGUudWlkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLnNlbmQoJ3JlbW92ZSB0aWxlJywgeyB1aWQ6IHRpbGUudWlkLCBzb3VyY2U6IHRoaXMuaWQgfSwgbnVsbCwgdGlsZS53b3JrZXJJRCk7XG4gICAgfSxcblxuICAgIF9yZWRvVGlsZVBsYWNlbWVudDogZnVuY3Rpb24odGlsZSkge1xuXG4gICAgICAgIGlmICghdGlsZS5sb2FkZWQgfHwgdGlsZS5yZWRvaW5nUGxhY2VtZW50KSB7XG4gICAgICAgICAgICB0aWxlLnJlZG9XaGVuRG9uZSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5zZW5kKCdyZWRvIHBsYWNlbWVudCcsIHtcbiAgICAgICAgICAgIHVpZDogdGlsZS51aWQsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWQsXG4gICAgICAgICAgICBhbmdsZTogdGhpcy5tYXAudHJhbnNmb3JtLmFuZ2xlLFxuICAgICAgICAgICAgcGl0Y2g6IHRoaXMubWFwLnRyYW5zZm9ybS5waXRjaCxcbiAgICAgICAgICAgIGNvbGxpc2lvbkRlYnVnOiB0aGlzLm1hcC5jb2xsaXNpb25EZWJ1Z1xuICAgICAgICB9LCBkb25lLmJpbmQodGhpcyksIHRpbGUud29ya2VySUQpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGRvbmUoXywgZGF0YSkge1xuICAgICAgICAgICAgdGlsZS5yZWxvYWRTeW1ib2xEYXRhKGRhdGEsIHRoaXMubWFwLnBhaW50ZXIpO1xuICAgICAgICAgICAgdGhpcy5maXJlKCd0aWxlLmxvYWQnLCB7dGlsZTogdGlsZX0pO1xuXG4gICAgICAgICAgICB0aWxlLnJlZG9pbmdQbGFjZW1lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aWxlLnJlZG9XaGVuRG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZG9UaWxlUGxhY2VtZW50KHRpbGUpO1xuICAgICAgICAgICAgICAgIHRpbGUucmVkb1doZW5Eb25lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIENvb3JkaW5hdGUgPSByZXF1aXJlKCcuLi9nZW8vY29vcmRpbmF0ZScpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWaWRlb1NvdXJjZTtcblxuLyoqXG4gKiBDcmVhdGUgYSBWaWRlbyBkYXRhIHNvdXJjZSBpbnN0YW5jZSBnaXZlbiBhbiBvcHRpb25zIG9iamVjdFxuICogQGNsYXNzIFZpZGVvU291cmNlXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiBAcGFyYW0ge1N0cmluZ3xBcnJheX0gb3B0aW9ucy51cmwgQSBzdHJpbmcgb3IgYXJyYXkgb2YgVVJMKHMpIHRvIHZpZGVvIGZpbGVzXG4gKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLmNvb3JkaW5hdGVzIGxhdCxsbmcgY29vcmRpbmF0ZXMgaW4gb3JkZXIgY2xvY2t3aXNlIHN0YXJ0aW5nIGF0IHRoZSB0b3AgbGVmdDogdGwsIHRyLCBiciwgYmxcbiAqIEBleGFtcGxlXG4gKiB2YXIgc291cmNlT2JqID0gbmV3IG1hcGJveGdsLlZpZGVvU291cmNlKHtcbiAqICAgIHVybDogW1xuICogICAgICAgICdodHRwczovL3d3dy5tYXBib3guY29tL3ZpZGVvcy9iYWx0aW1vcmUtc21va2UubXA0JyxcbiAqICAgICAgICAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS92aWRlb3MvYmFsdGltb3JlLXNtb2tlLndlYm0nXG4gKiAgICBdLFxuICogICAgY29vcmRpbmF0ZXM6IFtcbiAqICAgICAgICBbMzkuMTg1Nzk5MDcyMjk3NDgsIC03Ni41NDMzNTczNzIyODM5NF0sXG4gKiAgICAgICAgWzM5LjE4MzgzNjQ4NDc1ODcsIC03Ni41MjgwMzY1OTQzOTA4N10sXG4gKiAgICAgICAgWzM5LjE3NjgzMzkyNTA3NjA2LCAtNzYuNTI5NTM4NjMxNDM5Ml0sXG4gKiAgICAgICAgWzM5LjE3ODc2MzQ0MTA2NjQyLCAtNzYuNTQ1MjAyNzMyMDg2MThdXG4gKiAgICBdXG4gKiB9KTtcbiAqIG1hcC5hZGRTb3VyY2UoJ3NvbWUgaWQnLCBzb3VyY2VPYmopOyAvLyBhZGRcbiAqIG1hcC5yZW1vdmVTb3VyY2UoJ3NvbWUgaWQnKTsgIC8vIHJlbW92ZVxuICovXG5mdW5jdGlvbiBWaWRlb1NvdXJjZShvcHRpb25zKSB7XG4gICAgdGhpcy5jb29yZGluYXRlcyA9IG9wdGlvbnMuY29vcmRpbmF0ZXM7XG5cbiAgICBhamF4LmdldFZpZGVvKG9wdGlvbnMudXJsLCBmdW5jdGlvbihlcnIsIHZpZGVvKSB7XG4gICAgICAgIC8vIEBUT0RPIGhhbmRsZSBlcnJvcnMgdmlhIGV2ZW50LlxuICAgICAgICBpZiAoZXJyKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy52aWRlbyA9IHZpZGVvO1xuICAgICAgICB0aGlzLnZpZGVvLmxvb3AgPSB0cnVlO1xuXG4gICAgICAgIHZhciBsb29wSUQ7XG5cbiAgICAgICAgLy8gc3RhcnQgcmVwYWludGluZyB3aGVuIHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gICAgICAgIHRoaXMudmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheWluZycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbG9vcElEID0gdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5zZXQoSW5maW5pdHkpO1xuICAgICAgICAgICAgdGhpcy5tYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gc3RvcCByZXBhaW50aW5nIHdoZW4gdmlkZW8gc3RvcHNcbiAgICAgICAgdGhpcy52aWRlby5hZGRFdmVudExpc3RlbmVyKCdwYXVzZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5tYXAuc3R5bGUuYW5pbWF0aW9uTG9vcC5jYW5jZWwobG9vcElEKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLl9sb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0aGlzLm1hcCkge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJyk7XG4gICAgICAgIH1cbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5WaWRlb1NvdXJjZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgSFRNTCB2aWRlbyBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRWaWRlbzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvO1xuICAgIH0sXG5cbiAgICBvbkFkZDogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMubWFwID0gbWFwO1xuICAgICAgICBpZiAodGhpcy52aWRlbykge1xuICAgICAgICAgICAgdGhpcy52aWRlby5wbGF5KCk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVRpbGUoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogQ2FsY3VsYXRlIHdoaWNoIG1lcmNhdG9yIHRpbGUgaXMgc3VpdGFibGUgZm9yIHJlbmRlcmluZyB0aGUgdmlkZW8gaW5cbiAgICAgICAgICogYW5kIGNyZWF0ZSBhIGJ1ZmZlciB3aXRoIHRoZSBjb3JuZXIgY29vcmRpbmF0ZXMuIFRoZXNlIGNvb3JkaW5hdGVzXG4gICAgICAgICAqIG1heSBiZSBvdXRzaWRlIHRoZSB0aWxlLCBiZWNhdXNlIHJhc3RlciB0aWxlcyBhcmVuJ3QgY2xpcHBlZCB3aGVuIHJlbmRlcmluZy5cbiAgICAgICAgICovXG4gICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcbiAgICAgICAgdmFyIGNvb3JkcyA9IHRoaXMuY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uKGxhdGxuZykge1xuICAgICAgICAgICAgdmFyIGxvYyA9IExhdExuZy5jb252ZXJ0KGxhdGxuZyk7XG4gICAgICAgICAgICByZXR1cm4gbWFwLnRyYW5zZm9ybS5sb2NhdGlvbkNvb3JkaW5hdGUobG9jKS56b29tVG8oMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtaW5YID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtaW5ZID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBtYXhYID0gLUluZmluaXR5O1xuICAgICAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIGNvb3Jkc1tpXS5jb2x1bW4pO1xuICAgICAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIGNvb3Jkc1tpXS5yb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGR4ID0gbWF4WCAtIG1pblg7XG4gICAgICAgIHZhciBkeSA9IG1heFkgLSBtaW5ZO1xuICAgICAgICB2YXIgZE1heCA9IE1hdGgubWF4KGR4LCBkeSk7XG4gICAgICAgIHZhciBjZW50ZXIgPSBuZXcgQ29vcmRpbmF0ZSgobWluWCArIG1heFgpIC8gMiwgKG1pblkgKyBtYXhZKSAvIDIsIDApXG4gICAgICAgICAgICAuem9vbVRvKE1hdGguZmxvb3IoLU1hdGgubG9nKGRNYXgpIC8gTWF0aC5MTjIpKTtcblxuICAgICAgICB2YXIgdGlsZUV4dGVudCA9IDQwOTY7XG4gICAgICAgIHZhciB0aWxlQ29vcmRzID0gY29vcmRzLm1hcChmdW5jdGlvbihjb29yZCkge1xuICAgICAgICAgICAgdmFyIHpvb21lZENvb3JkID0gY29vcmQuem9vbVRvKGNlbnRlci56b29tKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZCgoem9vbWVkQ29vcmQuY29sdW1uIC0gY2VudGVyLmNvbHVtbikgKiB0aWxlRXh0ZW50KSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKCh6b29tZWRDb29yZC5yb3cgLSBjZW50ZXIucm93KSAqIHRpbGVFeHRlbnQpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGdsID0gbWFwLnBhaW50ZXIuZ2w7XG4gICAgICAgIHZhciBtYXhJbnQxNiA9IDMyNzY3O1xuICAgICAgICB2YXIgYXJyYXkgPSBuZXcgSW50MTZBcnJheShbXG4gICAgICAgICAgICB0aWxlQ29vcmRzWzBdLngsIHRpbGVDb29yZHNbMF0ueSwgMCwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMV0ueCwgdGlsZUNvb3Jkc1sxXS55LCBtYXhJbnQxNiwgMCxcbiAgICAgICAgICAgIHRpbGVDb29yZHNbM10ueCwgdGlsZUNvb3Jkc1szXS55LCAwLCBtYXhJbnQxNixcbiAgICAgICAgICAgIHRpbGVDb29yZHNbMl0ueCwgdGlsZUNvb3Jkc1syXS55LCBtYXhJbnQxNiwgbWF4SW50MTZcbiAgICAgICAgXSk7XG5cbiAgICAgICAgdGhpcy50aWxlID0gbmV3IFRpbGUoKTtcbiAgICAgICAgdGhpcy50aWxlLmJ1Y2tldHMgPSB7fTtcblxuICAgICAgICB0aGlzLnRpbGUuYm91bmRzQnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnRpbGUuYm91bmRzQnVmZmVyKTtcbiAgICAgICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGFycmF5LCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgICAgdGhpcy5jZW50ZXIgPSBjZW50ZXI7XG4gICAgfSxcblxuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvICYmIHRoaXMudmlkZW8ucmVhZHlTdGF0ZSA+PSAyO1xuICAgIH0sXG5cbiAgICB1cGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBub29wXG4gICAgfSxcblxuICAgIHJlbmRlcjogZnVuY3Rpb24obGF5ZXJzLCBwYWludGVyKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnZpZGVvLnJlYWR5U3RhdGUgPCAyKSByZXR1cm47IC8vIG5vdCBlbm91Z2ggZGF0YSBmb3IgY3VycmVudCBwb3NpdGlvblxuXG4gICAgICAgIHZhciBjID0gdGhpcy5jZW50ZXI7XG4gICAgICAgIHRoaXMudGlsZS5jYWxjdWxhdGVNYXRyaWNlcyhjLnpvb20sIGMuY29sdW1uLCBjLnJvdywgdGhpcy5tYXAudHJhbnNmb3JtLCBwYWludGVyKTtcblxuICAgICAgICB2YXIgZ2wgPSBwYWludGVyLmdsO1xuICAgICAgICBpZiAoIXRoaXMudGlsZS50ZXh0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLnRpbGUudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0aGlzLnZpZGVvKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGlsZS50ZXh0dXJlKTtcbiAgICAgICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgMCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy52aWRlbyk7XG4gICAgICAgIH1cblxuICAgICAgICBwYWludGVyLmRyYXdMYXllcnMobGF5ZXJzLCB0aGlzLnRpbGUucG9zTWF0cml4LCB0aGlzLnRpbGUpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihwb2ludCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgW10pO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQWN0b3IgPSByZXF1aXJlKCcuLi91dGlsL2FjdG9yJyk7XG52YXIgV29ya2VyVGlsZSA9IHJlcXVpcmUoJy4vd29ya2VyX3RpbGUnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIHZ0ID0gcmVxdWlyZSgndmVjdG9yLXRpbGUnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG52YXIgZ2VvanNvbnZ0ID0gcmVxdWlyZSgnZ2VvanNvbi12dCcpO1xudmFyIEdlb0pTT05XcmFwcGVyID0gcmVxdWlyZSgnLi9nZW9qc29uX3dyYXBwZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWxmKSB7XG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoc2VsZik7XG59O1xuXG5mdW5jdGlvbiBXb3JrZXIoc2VsZikge1xuICAgIHRoaXMuc2VsZiA9IHNlbGY7XG4gICAgdGhpcy5hY3RvciA9IG5ldyBBY3RvcihzZWxmLCB0aGlzKTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcblxuICAgIHRoaXMubG9hZGVkID0ge307XG4gICAgdGhpcy5sYXllcnMgPSBbXTtcbiAgICB0aGlzLmdlb0pTT05JbmRleGVzID0ge307XG59XG5cbnV0aWwuZXh0ZW5kKFdvcmtlci5wcm90b3R5cGUsIHtcbiAgICAnc2V0IGxheWVycyc6IGZ1bmN0aW9uKGxheWVycykge1xuICAgICAgICB0aGlzLmxheWVycyA9IGxheWVycztcbiAgICB9LFxuXG4gICAgJ2xvYWQgdGlsZSc6IGZ1bmN0aW9uKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHBhcmFtcy5zb3VyY2UsXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmICghdGhpcy5sb2FkaW5nW3NvdXJjZV0pXG4gICAgICAgICAgICB0aGlzLmxvYWRpbmdbc291cmNlXSA9IHt9O1xuXG5cbiAgICAgICAgdmFyIHRpbGUgPSB0aGlzLmxvYWRpbmdbc291cmNlXVt1aWRdID0gbmV3IFdvcmtlclRpbGUocGFyYW1zKTtcblxuICAgICAgICB0aWxlLnhociA9IGFqYXguZ2V0QXJyYXlCdWZmZXIocGFyYW1zLnVybCwgZG9uZS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBmdW5jdGlvbiBkb25lKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9hZGluZ1tzb3VyY2VdW3VpZF07XG5cbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuXG4gICAgICAgICAgICB0aWxlLmRhdGEgPSBuZXcgdnQuVmVjdG9yVGlsZShuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIHRpbGUucGFyc2UodGlsZS5kYXRhLCB0aGlzLmxheWVycywgdGhpcy5hY3RvciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRlZFtzb3VyY2VdID0gdGhpcy5sb2FkZWRbc291cmNlXSB8fCB7fTtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bdWlkXSA9IHRpbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbG9hZCB0aWxlJzogZnVuY3Rpb24ocGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgbG9hZGVkID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGVkICYmIGxvYWRlZFt1aWRdKSB7XG4gICAgICAgICAgICB2YXIgdGlsZSA9IGxvYWRlZFt1aWRdO1xuICAgICAgICAgICAgdGlsZS5wYXJzZSh0aWxlLmRhdGEsIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2Fib3J0IHRpbGUnOiBmdW5jdGlvbihwYXJhbXMpIHtcbiAgICAgICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuICAgICAgICBpZiAobG9hZGluZyAmJiBsb2FkaW5nW3VpZF0pIHtcbiAgICAgICAgICAgIGxvYWRpbmdbdWlkXS54aHIuYWJvcnQoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkaW5nW3VpZF07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3JlbW92ZSB0aWxlJzogZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIHVpZCA9IHBhcmFtcy51aWQ7XG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBsb2FkZWRbdWlkXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAncmVkbyBwbGFjZW1lbnQnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBsb2FkZWQgPSB0aGlzLmxvYWRlZFtwYXJhbXMuc291cmNlXSxcbiAgICAgICAgICAgIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbcGFyYW1zLnNvdXJjZV0sXG4gICAgICAgICAgICB1aWQgPSBwYXJhbXMudWlkO1xuXG4gICAgICAgIGlmIChsb2FkZWQgJiYgbG9hZGVkW3VpZF0pIHtcbiAgICAgICAgICAgIHZhciB0aWxlID0gbG9hZGVkW3VpZF07XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGlsZS5yZWRvUGxhY2VtZW50KHBhcmFtcy5hbmdsZSwgcGFyYW1zLnBpdGNoLCBwYXJhbXMuY29sbGlzaW9uRGVidWcpO1xuXG4gICAgICAgICAgICBpZiAocmVzdWx0LnJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdC5yZXN1bHQsIHJlc3VsdC50cmFuc2ZlcmFibGVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2UgaWYgKGxvYWRpbmcgJiYgbG9hZGluZ1t1aWRdKSB7XG4gICAgICAgICAgICBsb2FkaW5nW3VpZF0uYW5nbGUgPSBwYXJhbXMuYW5nbGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ3BhcnNlIGdlb2pzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBpbmRleERhdGEgPSBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgdGhpcy5nZW9KU09OSW5kZXhlc1twYXJhbXMuc291cmNlXSA9IGdlb2pzb252dChkYXRhLCB7YmFzZVpvb206IHBhcmFtcy5tYXhab29tfSk7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIC8vIFRPRE8gYWNjZXB0IHBhcmFtcy51cmwgZm9yIHVybHMgaW5zdGVhZFxuXG4gICAgICAgIC8vIE5vdCwgYmVjYXVzZSBvZiBzYW1lIG9yaWdpbiBpc3N1ZXMsIHVybHMgbXVzdCBlaXRoZXIgaW5jbHVkZSBhblxuICAgICAgICAvLyBleHBsaWNpdCBvcmlnaW4gb3IgYWJzb2x1dGUgcGF0aC5cbiAgICAgICAgLy8gaWU6IC9mb28vYmFyLmpzb24gb3IgaHR0cDovL2V4YW1wbGUuY29tL2Jhci5qc29uXG4gICAgICAgIC8vIGJ1dCBub3QgLi4vZm9vL2Jhci5qc29uXG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zLmRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBhamF4LmdldEpTT04ocGFyYW1zLmRhdGEsIGluZGV4RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpbmRleERhdGEobnVsbCwgcGFyYW1zLmRhdGEpO1xuICAgIH0sXG5cbiAgICAnbG9hZCBnZW9qc29uIHRpbGUnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBwYXJhbXMuc291cmNlLFxuICAgICAgICAgICAgY29vcmQgPSBwYXJhbXMuY29vcmQ7XG5cbiAgICAgICAgLy8gY29uc29sZS50aW1lKCd0aWxlICcgKyBjb29yZC56ICsgJyAnICsgY29vcmQueCArICcgJyArIGNvb3JkLnkpO1xuXG4gICAgICAgIHZhciBnZW9KU09OVGlsZSA9IHRoaXMuZ2VvSlNPTkluZGV4ZXNbc291cmNlXS5nZXRUaWxlKGNvb3JkLnosIGNvb3JkLngsIGNvb3JkLnkpO1xuXG4gICAgICAgIC8vIGNvbnNvbGUudGltZUVuZCgndGlsZSAnICsgY29vcmQueiArICcgJyArIGNvb3JkLnggKyAnICcgKyBjb29yZC55KTtcblxuICAgICAgICAvLyBpZiAoIWdlb0pTT05UaWxlKSBjb25zb2xlLmxvZygnbm90IGZvdW5kJywgdGhpcy5nZW9KU09OSW5kZXhlc1tzb3VyY2VdLCBjb29yZCk7XG5cbiAgICAgICAgaWYgKCFnZW9KU09OVGlsZSkgcmV0dXJuIGNhbGxiYWNrKG51bGwsIG51bGwpOyAvLyBub3RoaW5nIGluIHRoZSBnaXZlbiB0aWxlXG5cbiAgICAgICAgdmFyIHRpbGUgPSBuZXcgV29ya2VyVGlsZShwYXJhbXMpO1xuICAgICAgICB0aWxlLnBhcnNlKG5ldyBHZW9KU09OV3JhcHBlcihnZW9KU09OVGlsZS5mZWF0dXJlcyksIHRoaXMubGF5ZXJzLCB0aGlzLmFjdG9yLCBjYWxsYmFjayk7XG5cbiAgICAgICAgdGhpcy5sb2FkZWRbc291cmNlXSA9IHRoaXMubG9hZGVkW3NvdXJjZV0gfHwge307XG4gICAgICAgIHRoaXMubG9hZGVkW3NvdXJjZV1bcGFyYW1zLnVpZF0gPSB0aWxlO1xuICAgIH0sXG5cbiAgICAncXVlcnkgZmVhdHVyZXMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB0aWxlID0gdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV0gJiYgdGhpcy5sb2FkZWRbcGFyYW1zLnNvdXJjZV1bcGFyYW1zLnVpZF07XG4gICAgICAgIGlmICh0aWxlKSB7XG4gICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLnF1ZXJ5KHBhcmFtcywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgW10pO1xuICAgICAgICB9XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBGZWF0dXJlVHJlZSA9IHJlcXVpcmUoJy4uL2RhdGEvZmVhdHVyZV90cmVlJyk7XG52YXIgQ29sbGlzaW9uID0gcmVxdWlyZSgnLi4vc3ltYm9sL2NvbGxpc2lvbl90aWxlJyk7XG52YXIgQnVmZmVyU2V0ID0gcmVxdWlyZSgnLi4vZGF0YS9idWZmZXIvYnVmZmVyX3NldCcpO1xudmFyIGNyZWF0ZUJ1Y2tldCA9IHJlcXVpcmUoJy4uL2RhdGEvY3JlYXRlX2J1Y2tldCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdvcmtlclRpbGU7XG5cbmZ1bmN0aW9uIFdvcmtlclRpbGUocGFyYW1zKSB7XG4gICAgdGhpcy5jb29yZCA9IHBhcmFtcy5jb29yZDtcbiAgICB0aGlzLnVpZCA9IHBhcmFtcy51aWQ7XG4gICAgdGhpcy56b29tID0gcGFyYW1zLnpvb207XG4gICAgdGhpcy5tYXhab29tID0gcGFyYW1zLm1heFpvb207XG4gICAgdGhpcy50aWxlU2l6ZSA9IHBhcmFtcy50aWxlU2l6ZTtcbiAgICB0aGlzLnNvdXJjZSA9IHBhcmFtcy5zb3VyY2U7XG4gICAgdGhpcy5vdmVyc2NhbGluZyA9IHBhcmFtcy5vdmVyc2NhbGluZztcbiAgICB0aGlzLmFuZ2xlID0gcGFyYW1zLmFuZ2xlO1xuICAgIHRoaXMucGl0Y2ggPSBwYXJhbXMucGl0Y2g7XG4gICAgdGhpcy5jb2xsaXNpb25EZWJ1ZyA9IHBhcmFtcy5jb2xsaXNpb25EZWJ1ZztcblxuICAgIHRoaXMuc3RhY2tzID0ge307XG59XG5cbldvcmtlclRpbGUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oZGF0YSwgbGF5ZXJzLCBhY3RvciwgY2FsbGJhY2spIHtcblxuICAgIHRoaXMuc3RhdHVzID0gJ3BhcnNpbmcnO1xuXG4gICAgdGhpcy5mZWF0dXJlVHJlZSA9IG5ldyBGZWF0dXJlVHJlZSh0aGlzLmNvb3JkLCB0aGlzLm92ZXJzY2FsaW5nKTtcblxuICAgIHZhciBpLCBrLFxuICAgICAgICB0aWxlID0gdGhpcyxcbiAgICAgICAgbGF5ZXIsXG4gICAgICAgIGJ1Y2tldCxcbiAgICAgICAgYnVmZmVycyA9IG5ldyBCdWZmZXJTZXQoKSxcbiAgICAgICAgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb24gPSBuZXcgQ29sbGlzaW9uKHRoaXMuem9vbSwgNDA5NiwgdGhpcy50aWxlU2l6ZSksXG4gICAgICAgIGJ1Y2tldHMgPSB7fSxcbiAgICAgICAgYnVja2V0c0luT3JkZXIgPSB0aGlzLmJ1Y2tldHNJbk9yZGVyID0gW10sXG4gICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyID0ge307XG5cbiAgICBjb2xsaXNpb24ucmVzZXQodGhpcy5hbmdsZSwgdGhpcy5waXRjaCk7XG5cbiAgICAvLyBNYXAgbm9uLXJlZiBsYXllcnMgdG8gYnVja2V0cy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKGxheWVyLnJlZilcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBtaW56b29tID0gbGF5ZXIubWluem9vbTtcbiAgICAgICAgaWYgKG1pbnpvb20gJiYgdGhpcy56b29tIDwgbWluem9vbSAmJiBtaW56b29tIDwgdGhpcy5tYXhab29tKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIG1heHpvb20gPSBsYXllci5tYXh6b29tO1xuICAgICAgICBpZiAobWF4em9vbSAmJiB0aGlzLnpvb20gPj0gbWF4em9vbSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2aXNpYmlsaXR5ID0gbGF5ZXIubGF5b3V0LnZpc2liaWxpdHk7XG4gICAgICAgIGlmICh2aXNpYmlsaXR5ID09PSAnbm9uZScpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBjcmVhdGVCdWNrZXQobGF5ZXIsIGJ1ZmZlcnMsIGNvbGxpc2lvbiwgdGhpcy56b29tLCB0aGlzLm92ZXJzY2FsaW5nLCB0aGlzLmNvbGxpc2lvbkRlYnVnKTtcbiAgICAgICAgYnVja2V0LmxheWVycyA9IFtsYXllci5pZF07XG5cbiAgICAgICAgYnVja2V0c1tidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICBidWNrZXRzSW5PcmRlci5wdXNoKGJ1Y2tldCk7XG5cbiAgICAgICAgaWYgKGRhdGEubGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgICAgICB2YXIgc291cmNlTGF5ZXIgPSBsYXllclsnc291cmNlLWxheWVyJ107XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXSlcbiAgICAgICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltzb3VyY2VMYXllcl0gPSB7fTtcbiAgICAgICAgICAgIGJ1Y2tldHNCeVNvdXJjZUxheWVyW3NvdXJjZUxheWVyXVtidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZ2VvanNvbiB0aWxlXG4gICAgICAgICAgICBidWNrZXRzQnlTb3VyY2VMYXllcltidWNrZXQuaWRdID0gYnVja2V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5kZXggcmVmIGxheWVycy5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheWVyID0gbGF5ZXJzW2ldO1xuXG4gICAgICAgIGlmIChsYXllci5zb3VyY2UgIT09IHRoaXMuc291cmNlKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgaWYgKCFsYXllci5yZWYpXG4gICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICBidWNrZXQgPSBidWNrZXRzW2xheWVyLnJlZl07XG4gICAgICAgIGlmICghYnVja2V0KVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgYnVja2V0LmxheWVycy5wdXNoKGxheWVyLmlkKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0ZW50ID0gNDA5NjtcblxuICAgIC8vIHJlYWQgZWFjaCBsYXllciwgYW5kIHNvcnQgaXRzIGZlYXR1cmVzIGludG8gYnVja2V0c1xuICAgIGlmIChkYXRhLmxheWVycykge1xuICAgICAgICAvLyB2ZWN0b3J0aWxlXG4gICAgICAgIGZvciAoayBpbiBidWNrZXRzQnlTb3VyY2VMYXllcikge1xuICAgICAgICAgICAgbGF5ZXIgPSBkYXRhLmxheWVyc1trXTtcbiAgICAgICAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGxheWVyLmV4dGVudCkgZXh0ZW50ID0gbGF5ZXIuZXh0ZW50O1xuICAgICAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMobGF5ZXIsIGJ1Y2tldHNCeVNvdXJjZUxheWVyW2tdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGdlb2pzb25cbiAgICAgICAgc29ydExheWVySW50b0J1Y2tldHMoZGF0YSwgYnVja2V0c0J5U291cmNlTGF5ZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNvcnRMYXllckludG9CdWNrZXRzKGxheWVyLCBidWNrZXRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGF5ZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBmZWF0dXJlID0gbGF5ZXIuZmVhdHVyZShpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBidWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1Y2tldCA9IGJ1Y2tldHNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0LmZpbHRlcihmZWF0dXJlKSkge1xuICAgICAgICAgICAgICAgICAgICBidWNrZXQuZmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcHJldlBsYWNlbWVudEJ1Y2tldDtcbiAgICB2YXIgcmVtYWluaW5nID0gYnVja2V0c0luT3JkZXIubGVuZ3RoO1xuXG4gICAgLypcbiAgICAgKiAgVGhlIGFzeW5jIHBhcnNpbmcgaGVyZSBpcyBhIGJpdCB0cmlja3kuXG4gICAgICogIFNvbWUgYnVja2V0cyBkZXBlbmQgb24gcmVzb3VyY2VzIHRoYXQgbWF5IG5lZWQgdG8gYmUgbG9hZGVkIGFzeW5jIChnbHlwaHMpLlxuICAgICAqICBTb21lIGJ1Y2tldHMgbmVlZCB0byBiZSBwYXJzZWQgaW4gb3JkZXIgKHRvIGdldCBjb2xsaXNpb24gcHJpb3JpdGllcyByaWdodCkuXG4gICAgICpcbiAgICAgKiAgRGVwZW5kZW5jaWVzIGNhbGxzIGFyZSBpbml0aWF0ZWQgZmlyc3QgdG8gZ2V0IHRob3NlIHJvbGxpbmcuXG4gICAgICogIEJ1Y2tldHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlciwgYXJlbid0IHRvIHNhdmUgdGltZS5cbiAgICAgKi9cblxuICAgIGZvciAoaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWNrZXQgPSBidWNrZXRzSW5PcmRlcltpXTtcblxuICAgICAgICAvLyBMaW5rIGJ1Y2tldHMgdGhhdCBuZWVkIHRvIGJlIHBhcnNlZCBpbiBvcmRlclxuICAgICAgICBpZiAoYnVja2V0LmNvbGxpc2lvbikge1xuICAgICAgICAgICAgaWYgKHByZXZQbGFjZW1lbnRCdWNrZXQpIHtcbiAgICAgICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0Lm5leHQgPSBidWNrZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Y2tldC5wcmV2aW91c1BsYWNlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGxhY2VtZW50QnVja2V0ID0gYnVja2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ1Y2tldC5nZXREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5nZXREZXBlbmRlbmNpZXModGhpcywgYWN0b3IsIGRlcGVuZGVuY2llc0RvbmUoYnVja2V0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbW1lZGlhdGVseSBwYXJzZSBidWNrZXRzIHdoZXJlIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGFuZCBubyBkZXBlbmRlbmNpZXNcbiAgICAgICAgaWYgKCFidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQuZ2V0RGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVwZW5kZW5jaWVzRG9uZShidWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgYnVja2V0LmRlcGVuZGVuY2llc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICBwYXJzZUJ1Y2tldCh0aWxlLCBidWNrZXQsIGVycik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VCdWNrZXQodGlsZSwgYnVja2V0LCBza2lwKSB7XG4gICAgICAgIGlmIChidWNrZXQuZ2V0RGVwZW5kZW5jaWVzICYmICFidWNrZXQuZGVwZW5kZW5jaWVzTG9hZGVkKSByZXR1cm47XG4gICAgICAgIGlmIChidWNrZXQuY29sbGlzaW9uICYmICFidWNrZXQucHJldmlvdXNQbGFjZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoIXNraXApIHtcbiAgICAgICAgICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5mZWF0dXJlcy5sZW5ndGgpIGJ1Y2tldC5hZGRGZWF0dXJlcygpO1xuICAgICAgICAgICAgdmFyIHRpbWUgPSBEYXRlLm5vdygpIC0gbm93O1xuICAgICAgICAgICAgaWYgKGJ1Y2tldC5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnVja2V0LmZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmZWF0dXJlID0gYnVja2V0LmZlYXR1cmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aWxlLmZlYXR1cmVUcmVlLmluc2VydChmZWF0dXJlLmJib3goKSwgYnVja2V0LmxheWVycywgZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMgPSBzZWxmLmJ1Y2tldFN0YXRzIHx8IHtfdG90YWw6IDB9O1xuICAgICAgICAgICAgICAgIHNlbGYuYnVja2V0U3RhdHMuX3RvdGFsICs9IHRpbWU7XG4gICAgICAgICAgICAgICAgc2VsZi5idWNrZXRTdGF0c1tidWNrZXQuaWRdID0gKHNlbGYuYnVja2V0U3RhdHNbYnVja2V0LmlkXSB8fCAwKSArIHRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZW1haW5pbmctLTtcblxuICAgICAgICBpZiAoIXJlbWFpbmluZykge1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJ5IHBhcnNpbmcgdGhlIG5leHQgYnVja2V0LCBpZiBpdCBpcyByZWFkeVxuICAgICAgICBpZiAoYnVja2V0Lm5leHQpIHtcbiAgICAgICAgICAgIGJ1Y2tldC5uZXh0LnByZXZpb3VzUGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcnNlQnVja2V0KHRpbGUsIGJ1Y2tldC5uZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbmUoKSB7XG5cbiAgICAgICAgdGlsZS5zdGF0dXMgPSAnZG9uZSc7XG5cbiAgICAgICAgaWYgKHRpbGUucmVkb1BsYWNlbWVudEFmdGVyRG9uZSkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRpbGUucmVkb1BsYWNlbWVudCh0aWxlLmFuZ2xlLCB0aWxlLnBpdGNoKS5yZXN1bHQ7XG4gICAgICAgICAgICBidWZmZXJzLmdseXBoVmVydGV4ID0gcmVzdWx0LmJ1ZmZlcnMuZ2x5cGhWZXJ0ZXg7XG4gICAgICAgICAgICBidWZmZXJzLmljb25WZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5pY29uVmVydGV4O1xuICAgICAgICAgICAgYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXggPSByZXN1bHQuYnVmZmVycy5jb2xsaXNpb25Cb3hWZXJ0ZXg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhbnNmZXJhYmxlcyA9IFtdLFxuICAgICAgICAgICAgZWxlbWVudEdyb3VwcyA9IHt9O1xuXG4gICAgICAgIGZvciAoayBpbiBidWZmZXJzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlcmFibGVzLnB1c2goYnVmZmVyc1trXS5hcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGsgaW4gYnVja2V0cykge1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1trXSA9IGJ1Y2tldHNba10uZWxlbWVudEdyb3VwcztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHtcbiAgICAgICAgICAgIGVsZW1lbnRHcm91cHM6IGVsZW1lbnRHcm91cHMsXG4gICAgICAgICAgICBidWZmZXJzOiBidWZmZXJzLFxuICAgICAgICAgICAgZXh0ZW50OiBleHRlbnRcbiAgICAgICAgfSwgdHJhbnNmZXJhYmxlcyk7XG4gICAgfVxufTtcblxuV29ya2VyVGlsZS5wcm90b3R5cGUucmVkb1BsYWNlbWVudCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCwgY29sbGlzaW9uRGVidWcpIHtcblxuICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gJ2RvbmUnKSB7XG4gICAgICAgIHRoaXMucmVkb1BsYWNlbWVudEFmdGVyRG9uZSA9IHRydWU7XG4gICAgICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHZhciBidWZmZXJzID0gbmV3IEJ1ZmZlclNldCgpO1xuICAgIHZhciB0cmFuc2ZlcmFibGVzID0gW107XG4gICAgdmFyIGVsZW1lbnRHcm91cHMgPSB7fTtcbiAgICB2YXIgY29sbGlzaW9uID0gdGhpcy5jb2xsaXNpb247XG5cbiAgICBjb2xsaXNpb24ucmVzZXQoYW5nbGUsIHBpdGNoKTtcblxuICAgIHZhciBidWNrZXRzSW5PcmRlciA9IHRoaXMuYnVja2V0c0luT3JkZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWNrZXRzSW5PcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYnVja2V0ID0gYnVja2V0c0luT3JkZXJbaV07XG5cbiAgICAgICAgaWYgKGJ1Y2tldC50eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgYnVja2V0LnBsYWNlRmVhdHVyZXMoYnVmZmVycywgY29sbGlzaW9uRGVidWcpO1xuICAgICAgICAgICAgZWxlbWVudEdyb3Vwc1tidWNrZXQuaWRdID0gYnVja2V0LmVsZW1lbnRHcm91cHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBrIGluIGJ1ZmZlcnMpIHtcbiAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGJ1ZmZlcnNba10uYXJyYXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHJlc3VsdDoge1xuICAgICAgICAgICAgZWxlbWVudEdyb3VwczogZWxlbWVudEdyb3VwcyxcbiAgICAgICAgICAgIGJ1ZmZlcnM6IGJ1ZmZlcnNcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNmZXJhYmxlczogdHJhbnNmZXJhYmxlc1xuICAgIH07XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQW5pbWF0aW9uTG9vcDtcblxuZnVuY3Rpb24gQW5pbWF0aW9uTG9vcCgpIHtcbiAgICB0aGlzLm4gPSAwO1xuICAgIHRoaXMudGltZXMgPSBbXTtcbn1cblxuLy8gQXJlIGFsbCBhbmltYXRpb25zIGRvbmU/XG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5zdG9wcGVkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQudGltZSA+PSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgIH0pO1xuICAgIHJldHVybiAhdGhpcy50aW1lcy5sZW5ndGg7XG59O1xuXG4vLyBBZGQgYSBuZXcgYW5pbWF0aW9uIHRoYXQgd2lsbCBydW4gdCBtaWxsaXNlY29uZHNcbi8vIFJldHVybnMgYW4gaWQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgaXQgbGF5ZXJcbkFuaW1hdGlvbkxvb3AucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aGlzLnRpbWVzLnB1c2goeyBpZDogdGhpcy5uLCB0aW1lOiB0ICsgKG5ldyBEYXRlKCkpLmdldFRpbWUoKSB9KTtcbiAgICByZXR1cm4gdGhpcy5uKys7XG59O1xuXG4vLyBDYW5jZWwgYW4gYW5pbWF0aW9uXG5BbmltYXRpb25Mb29wLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbihuKSB7XG4gICAgdGhpcy50aW1lcyA9IHRoaXMudGltZXMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQuaWQgIT09IG47XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi91dGlsL2FqYXgnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSW1hZ2VTcHJpdGU7XG5cbmZ1bmN0aW9uIEltYWdlU3ByaXRlKGJhc2UpIHtcbiAgICB0aGlzLmJhc2UgPSBiYXNlO1xuICAgIHRoaXMucmV0aW5hID0gYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMTtcblxuICAgIGJhc2UgPSB0aGlzLmJhc2UgKyAodGhpcy5yZXRpbmEgPyAnQDJ4JyA6ICcnKTtcblxuICAgIGFqYXguZ2V0SlNPTihiYXNlICsgJy5qc29uJywgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnZXJyb3InLCB7ZXJyb3I6IGVycn0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgaWYgKHRoaXMuaW1nKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgYWpheC5nZXRJbWFnZShiYXNlICsgJy5wbmcnLCBmdW5jdGlvbihlcnIsIGltZykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByZW11bHRpcGx5IHRoZSBzcHJpdGVcbiAgICAgICAgdmFyIGRhdGEgPSBpbWcuZ2V0RGF0YSgpO1xuICAgICAgICB2YXIgbmV3ZGF0YSA9IGltZy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgICAgICAgIHZhciBhbHBoYSA9IGRhdGFbaSArIDNdIC8gMjU1O1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMF0gPSBkYXRhW2kgKyAwXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMV0gPSBkYXRhW2kgKyAxXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgMl0gPSBkYXRhW2kgKyAyXSAqIGFscGhhO1xuICAgICAgICAgICAgbmV3ZGF0YVtpICsgM10gPSBkYXRhW2kgKyAzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW1nID0gaW1nO1xuICAgICAgICBpZiAodGhpcy5kYXRhKSB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcykpO1xufVxuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50ZWQpO1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5sb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gISEodGhpcy5kYXRhICYmIHRoaXMuaW1nKTtcbn07XG5cbkltYWdlU3ByaXRlLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbigvKmdsKi8pIHtcbiAgICBpZiAoYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID4gMSAhPT0gdGhpcy5yZXRpbmEpIHtcbiAgICAgICAgdmFyIG5ld1Nwcml0ZSA9IG5ldyBJbWFnZVNwcml0ZSh0aGlzLmJhc2UpO1xuICAgICAgICBuZXdTcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuaW1nID0gbmV3U3ByaXRlLmltZztcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ld1Nwcml0ZS5kYXRhO1xuICAgICAgICAgICAgdGhpcy5yZXRpbmEgPSBuZXdTcHJpdGUucmV0aW5hO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIFNwcml0ZVBvc2l0aW9uKCkge31cblNwcml0ZVBvc2l0aW9uLnByb3RvdHlwZSA9IHsgeDogMCwgeTogMCwgd2lkdGg6IDAsIGhlaWdodDogMCwgcGl4ZWxSYXRpbzogMSwgc2RmOiBmYWxzZSB9O1xuXG5JbWFnZVNwcml0ZS5wcm90b3R5cGUuZ2V0U3ByaXRlUG9zaXRpb24gPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCgpKSByZXR1cm4gbmV3IFNwcml0ZVBvc2l0aW9uKCk7XG5cbiAgICB2YXIgcG9zID0gdGhpcy5kYXRhICYmIHRoaXMuZGF0YVtuYW1lXTtcbiAgICBpZiAocG9zICYmIHRoaXMuaW1nKSByZXR1cm4gcG9zO1xuXG4gICAgcmV0dXJuIG5ldyBTcHJpdGVQb3NpdGlvbigpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge307XG5cbnJlZmVyZW5jZS5sYXlvdXQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BzKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgIHRoaXNbcF0gPSBwcm9wc1twXTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHByb3AgaW4gcHJvcGVydGllcykge1xuICAgICAgICBpZiAocHJvcGVydGllc1twcm9wXS5kZWZhdWx0ID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBQcm9wZXJ0aWVzLnByb3RvdHlwZVtwcm9wXSA9IHByb3BlcnRpZXNbcHJvcF0uZGVmYXVsdDtcbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHNbY2xhc3NOYW1lLnJlcGxhY2UoJ2xheW91dF8nLCAnJyldID0gUHJvcGVydGllcztcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi9yZWZlcmVuY2UnKTtcbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5yZWZlcmVuY2UucGFpbnQuZm9yRWFjaChmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB2YXIgQ2FsY3VsYXRlZCA9IGZ1bmN0aW9uKCkge307XG5cbiAgICB2YXIgcHJvcGVydGllcyA9IHJlZmVyZW5jZVtjbGFzc05hbWVdO1xuICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcykge1xuICAgICAgICB2YXIgcHJvcCA9IHByb3BlcnRpZXNbcF0sXG4gICAgICAgICAgICB2YWx1ZSA9IHByb3AuZGVmYXVsdDtcblxuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG4gICAgICAgIGlmIChwcm9wLnR5cGUgPT09ICdjb2xvcicpIHZhbHVlID0gcGFyc2VDU1NDb2xvcih2YWx1ZSk7XG5cbiAgICAgICAgQ2FsY3VsYXRlZC5wcm90b3R5cGVbcF0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBDYWxjdWxhdGVkLnByb3RvdHlwZS5oaWRkZW4gPSBmYWxzZTtcbiAgICBtb2R1bGUuZXhwb3J0c1tjbGFzc05hbWUucmVwbGFjZSgncGFpbnRfJywgJycpXSA9IENhbGN1bGF0ZWQ7XG59KTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvcmVmZXJlbmNlL2xhdGVzdCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIFNvdXJjZSA9IHJlcXVpcmUoJy4uL3NvdXJjZS9zb3VyY2UnKTtcbnZhciBTdHlsZUxheWVyID0gcmVxdWlyZSgnLi9zdHlsZV9sYXllcicpO1xudmFyIEltYWdlU3ByaXRlID0gcmVxdWlyZSgnLi9pbWFnZV9zcHJpdGUnKTtcbnZhciBHbHlwaFNvdXJjZSA9IHJlcXVpcmUoJy4uL3N5bWJvbC9nbHlwaF9zb3VyY2UnKTtcbnZhciBHbHlwaEF0bGFzID0gcmVxdWlyZSgnLi4vc3ltYm9sL2dseXBoX2F0bGFzJyk7XG52YXIgU3ByaXRlQXRsYXMgPSByZXF1aXJlKCcuLi9zeW1ib2wvc3ByaXRlX2F0bGFzJyk7XG52YXIgTGluZUF0bGFzID0gcmVxdWlyZSgnLi4vcmVuZGVyL2xpbmVfYXRsYXMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL3V0aWwvYWpheCcpO1xudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplU3R5bGVVUkw7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi91dGlsL2Rpc3BhdGNoZXInKTtcbnZhciBBbmltYXRpb25Mb29wID0gcmVxdWlyZSgnLi9hbmltYXRpb25fbG9vcCcpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnbWFwYm94LWdsLXN0eWxlLXNwZWMvbGliL3ZhbGlkYXRlL2xhdGVzdCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlO1xuXG5mdW5jdGlvbiBTdHlsZShzdHlsZXNoZWV0LCBhbmltYXRpb25Mb29wKSB7XG4gICAgdGhpcy5hbmltYXRpb25Mb29wID0gYW5pbWF0aW9uTG9vcCB8fCBuZXcgQW5pbWF0aW9uTG9vcCgpO1xuICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKE1hdGgubWF4KGJyb3dzZXIuaGFyZHdhcmVDb25jdXJyZW5jeSAtIDEsIDEpLCB0aGlzKTtcbiAgICB0aGlzLmdseXBoQXRsYXMgPSBuZXcgR2x5cGhBdGxhcygxMDI0LCAxMDI0KTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzID0gbmV3IFNwcml0ZUF0bGFzKDUxMiwgNTEyKTtcbiAgICB0aGlzLnNwcml0ZUF0bGFzLnJlc2l6ZShicm93c2VyLmRldmljZVBpeGVsUmF0aW8pO1xuICAgIHRoaXMubGluZUF0bGFzID0gbmV3IExpbmVBdGxhcygyNTYsIDUxMik7XG5cbiAgICB0aGlzLl9sYXllcnMgPSB7fTtcbiAgICB0aGlzLl9vcmRlciAgPSBbXTtcbiAgICB0aGlzLl9ncm91cHMgPSBbXTtcbiAgICB0aGlzLnNvdXJjZXMgPSB7fTtcblxuICAgIHRoaXMuem9vbUhpc3RvcnkgPSB7fTtcblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFNvdXJjZUV2ZW50JyxcbiAgICAgICAgJ19mb3J3YXJkVGlsZUV2ZW50JyxcbiAgICAgICAgJ19yZWRvUGxhY2VtZW50J1xuICAgIF0sIHRoaXMpO1xuXG4gICAgdmFyIGxvYWRlZCA9IGZ1bmN0aW9uKGVyciwgc3R5bGVzaGVldCkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2Vycm9yJywge2Vycm9yOiBlcnJ9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKHN0eWxlc2hlZXQpO1xuICAgICAgICBpZiAodmFsaWQubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YWxpZC5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fbG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHlsZXNoZWV0ID0gc3R5bGVzaGVldDtcblxuICAgICAgICB2YXIgc291cmNlcyA9IHN0eWxlc2hlZXQuc291cmNlcztcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gc291cmNlcykge1xuICAgICAgICAgICAgdGhpcy5hZGRTb3VyY2UoaWQsIHNvdXJjZXNbaWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHlsZXNoZWV0LnNwcml0ZSkge1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUgPSBuZXcgSW1hZ2VTcHJpdGUoc3R5bGVzaGVldC5zcHJpdGUpO1xuICAgICAgICAgICAgdGhpcy5zcHJpdGUub24oJ2xvYWQnLCB0aGlzLmZpcmUuYmluZCh0aGlzLCAnY2hhbmdlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5nbHlwaFNvdXJjZSA9IG5ldyBHbHlwaFNvdXJjZShzdHlsZXNoZWV0LmdseXBocywgdGhpcy5nbHlwaEF0bGFzKTtcbiAgICAgICAgdGhpcy5fcmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBpZiAodHlwZW9mIHN0eWxlc2hlZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFqYXguZ2V0SlNPTihub3JtYWxpemVVUkwoc3R5bGVzaGVldCksIGxvYWRlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnJvd3Nlci5mcmFtZShsb2FkZWQuYmluZCh0aGlzLCBudWxsLCBzdHlsZXNoZWV0KSk7XG4gICAgfVxufVxuXG5TdHlsZS5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwge1xuICAgIF9sb2FkZWQ6IGZhbHNlLFxuXG4gICAgbG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKVxuICAgICAgICAgICAgaWYgKCF0aGlzLnNvdXJjZXNbaWRdLmxvYWRlZCgpKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAodGhpcy5zcHJpdGUgJiYgIXRoaXMuc3ByaXRlLmxvYWRlZCgpKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBfcmVzb2x2ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBpZCwgbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5fbGF5ZXJzID0ge307XG4gICAgICAgIHRoaXMuX29yZGVyICA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zdHlsZXNoZWV0LmxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGF5ZXIgPSBuZXcgU3R5bGVMYXllcih0aGlzLnN0eWxlc2hlZXQubGF5ZXJzW2ldLCB0aGlzLnN0eWxlc2hlZXQuY29uc3RhbnRzIHx8IHt9KTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgICAgIHRoaXMuX29yZGVyLnB1c2gobGF5ZXIuaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsYXlvdXQgcHJvcGVydGllcy5cbiAgICAgICAgZm9yIChpZCBpbiB0aGlzLl9sYXllcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZUxheW91dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzb2x2ZSByZWZlcmVuY2UgYW5kIHBhaW50IHByb3BlcnRpZXMuXG4gICAgICAgIGZvciAoaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLnJlc29sdmVSZWZlcmVuY2UodGhpcy5fbGF5ZXJzKTtcbiAgICAgICAgICAgIHRoaXMuX2xheWVyc1tpZF0ucmVzb2x2ZVBhaW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICB9LFxuXG4gICAgX2dyb3VwTGF5ZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdyb3VwO1xuXG4gICAgICAgIHRoaXMuX2dyb3VwcyA9IFtdO1xuXG4gICAgICAgIC8vIFNwbGl0IGludG8gZ3JvdXBzIG9mIGNvbnNlY3V0aXZlIHRvcC1sZXZlbCBsYXllcnMgd2l0aCB0aGUgc2FtZSBzb3VyY2UuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fb3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1t0aGlzLl9vcmRlcltpXV07XG5cbiAgICAgICAgICAgIGlmICghZ3JvdXAgfHwgbGF5ZXIuc291cmNlICE9PSBncm91cC5zb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBncm91cCA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwLnNvdXJjZSA9IGxheWVyLnNvdXJjZTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ncm91cHMucHVzaChncm91cCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdyb3VwLnB1c2gobGF5ZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9icm9hZGNhc3RMYXllcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb3JkZXJlZCA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgb3JkZXJlZC5wdXNoKHRoaXMuX2xheWVyc1tpZF0uanNvbigpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlci5icm9hZGNhc3QoJ3NldCBsYXllcnMnLCBvcmRlcmVkKTtcbiAgICB9LFxuXG4gICAgX2Nhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpIHJldHVybjtcblxuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLl9sYXllcnNbaWRdLmNhc2NhZGUoY2xhc3Nlcywgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICB0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbiB8fCB7fSxcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnKTtcbiAgICB9LFxuXG4gICAgX3JlY2FsY3VsYXRlOiBmdW5jdGlvbih6KSB7XG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuc291cmNlcylcbiAgICAgICAgICAgIHRoaXMuc291cmNlc1tpZF0udXNlZCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZVpvb21IaXN0b3J5KHopO1xuXG4gICAgICAgIHRoaXMucmFzdGVyRmFkZUR1cmF0aW9uID0gMzAwO1xuICAgICAgICBmb3IgKGlkIGluIHRoaXMuX2xheWVycykge1xuICAgICAgICAgICAgdmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcblxuICAgICAgICAgICAgaWYgKGxheWVyLnJlY2FsY3VsYXRlKHosIHRoaXMuem9vbUhpc3RvcnkpICYmIGxheWVyLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1heFpvb21UcmFuc2l0aW9uRHVyYXRpb24gPSAzMDA7XG4gICAgICAgIGlmIChNYXRoLmZsb29yKHRoaXMueikgIT09IE1hdGguZmxvb3IoeikpIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uTG9vcC5zZXQobWF4Wm9vbVRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnogPSB6O1xuICAgICAgICB0aGlzLmZpcmUoJ3pvb20nKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVpvb21IaXN0b3J5OiBmdW5jdGlvbih6KSB7XG5cbiAgICAgICAgdmFyIHpoID0gdGhpcy56b29tSGlzdG9yeTtcblxuICAgICAgICBpZiAoemgubGFzdEludGVnZXJab29tID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGZpcnN0IHRpbWVcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbSA9IE1hdGguZmxvb3Ioeik7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb21UaW1lID0gMDtcbiAgICAgICAgICAgIHpoLmxhc3Rab29tID0gejtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgYW4gaW50ZWdlciB6b29tIGxldmVsIGFzIHBhc3NlZCBzaW5jZSB0aGUgbGFzdCBmcmFtZVxuICAgICAgICAvLyBhbmQgaWYgeWVzLCByZWNvcmQgaXQgd2l0aCB0aGUgdGltZS4gVXNlZCBmb3IgdHJhbnNpdGlvbmluZyBwYXR0ZXJucy5cbiAgICAgICAgaWYgKE1hdGguZmxvb3IoemgubGFzdFpvb20pIDwgTWF0aC5mbG9vcih6KSkge1xuICAgICAgICAgICAgemgubGFzdEludGVnZXJab29tID0gTWF0aC5mbG9vcih6KTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoTWF0aC5mbG9vcih6aC5sYXN0Wm9vbSkgPiBNYXRoLmZsb29yKHopKSB7XG4gICAgICAgICAgICB6aC5sYXN0SW50ZWdlclpvb20gPSBNYXRoLmZsb29yKHogKyAxKTtcbiAgICAgICAgICAgIHpoLmxhc3RJbnRlZ2VyWm9vbVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgemgubGFzdFpvb20gPSB6O1xuICAgIH0sXG5cbiAgICBhZGRTb3VyY2U6IGZ1bmN0aW9uKGlkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMuc291cmNlc1tpZF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBpcyBhbHJlYWR5IGEgc291cmNlIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIHNvdXJjZSA9IFNvdXJjZS5jcmVhdGUoc291cmNlKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2lkXSA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlLmlkID0gaWQ7XG4gICAgICAgIHNvdXJjZS5zdHlsZSA9IHRoaXM7XG4gICAgICAgIHNvdXJjZS5kaXNwYXRjaGVyID0gdGhpcy5kaXNwYXRjaGVyO1xuICAgICAgICBzb3VyY2UuZ2x5cGhBdGxhcyA9IHRoaXMuZ2x5cGhBdGxhcztcbiAgICAgICAgc291cmNlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCdjaGFuZ2UnLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUucmVtb3ZlJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudCk7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLmFkZCcsIHtzb3VyY2U6IHNvdXJjZX0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgc291cmNlIGZyb20gdGhpcyBzdHlsZXNoZWV0LCBnaXZlbiBpdHMgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBzb3VyY2UgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMge1N0eWxlfSB0aGlzIHN0eWxlXG4gICAgICogQHRocm93cyB7RXJyb3J9IGlmIG5vIHNvdXJjZSBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlU291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHNvdXJjZSB3aXRoIHRoaXMgSUQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgIHNvdXJjZVxuICAgICAgICAgICAgLm9mZignbG9hZCcsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ2Vycm9yJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZignY2hhbmdlJywgdGhpcy5fZm9yd2FyZFNvdXJjZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5hZGQnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vZmYoJ3RpbGUuZXJyb3InLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9mZigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KTtcbiAgICAgICAgdGhpcy5maXJlKCdzb3VyY2UucmVtb3ZlJywge3NvdXJjZTogc291cmNlfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBzb3VyY2UgYnkgaWQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkIGlkIG9mIHRoZSBkZXNpcmVkIHNvdXJjZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IHNvdXJjZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0U291cmNlOiBmdW5jdGlvbihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2VzW2lkXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgbGF5ZXIgdG8gdGhlIG1hcCBzdHlsZS4gVGhlIGxheWVyIHdpbGwgYmUgaW5zZXJ0ZWQgYmVmb3JlIHRoZSBsYXllciB3aXRoXG4gICAgICogSUQgYGJlZm9yZWAsIG9yIGFwcGVuZGVkIGlmIGBiZWZvcmVgIGlzIG9taXR0ZWQuXG4gICAgICogQHBhcmFtIHtTdHlsZUxheWVyfE9iamVjdH0gbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGJlZm9yZSAgSUQgb2YgYW4gZXhpc3RpbmcgbGF5ZXIgdG8gaW5zZXJ0IGJlZm9yZVxuICAgICAqIEBmaXJlcyBsYXllci5hZGRcbiAgICAgKiBAcmV0dXJucyB7U3R5bGV9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZExheWVyOiBmdW5jdGlvbihsYXllciwgYmVmb3JlKSB7XG4gICAgICAgIGlmICh0aGlzLl9sYXllcnNbbGF5ZXIuaWRdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgYWxyZWFkeSBhIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKGxheWVyIGluc3RhbmNlb2YgU3R5bGVMYXllcikpIHtcbiAgICAgICAgICAgIGxheWVyID0gbmV3IFN0eWxlTGF5ZXIobGF5ZXIsIHRoaXMuc3R5bGVzaGVldC5jb25zdGFudHMgfHwge30pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xheWVyc1tsYXllci5pZF0gPSBsYXllcjtcbiAgICAgICAgdGhpcy5fb3JkZXIuc3BsaWNlKGJlZm9yZSA/IHRoaXMuX29yZGVyLmluZGV4T2YoYmVmb3JlKSA6IEluZmluaXR5LCAwLCBsYXllci5pZCk7XG4gICAgICAgIGxheWVyLnJlc29sdmVMYXlvdXQoKTtcbiAgICAgICAgbGF5ZXIucmVzb2x2ZVJlZmVyZW5jZSh0aGlzLl9sYXllcnMpO1xuICAgICAgICBsYXllci5yZXNvbHZlUGFpbnQoKTtcbiAgICAgICAgdGhpcy5fZ3JvdXBMYXllcnMoKTtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuZmlyZSgnbGF5ZXIuYWRkJywge2xheWVyOiBsYXllcn0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgbGF5ZXIgZnJvbSB0aGlzIHN0eWxlc2hlZXQsIGdpdmVuIGl0cyBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGxheWVyIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtTdHlsZX0gdGhpcyBzdHlsZVxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBsYXllciBpcyBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XG4gICAgICAgIGlmIChsYXllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIGxheWVyIHdpdGggdGhpcyBJRCcpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fbGF5ZXJzW2ldLnJlZiA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxheWVyKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xuICAgICAgICB0aGlzLl9vcmRlci5zcGxpY2UodGhpcy5fb3JkZXIuaW5kZXhPZihpZCksIDEpO1xuICAgICAgICB0aGlzLl9ncm91cExheWVycygpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5maXJlKCdsYXllci5yZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllciBieSBpZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIGRlc2lyZWQgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyB7TGF5ZXJ9IGxheWVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXllcjogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xheWVyc1tpZF07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIElmIGEgbGF5ZXIgaGFzIGEgYHJlZmAgcHJvcGVydHkgdGhhdCBtYWtlcyBpdCBkZXJpdmUgc29tZSB2YWx1ZXNcbiAgICAgKiBmcm9tIGFub3RoZXIgbGF5ZXIsIHJldHVybiB0aGF0IHJlZmVyZW50IGxheWVyLiBPdGhlcndpc2UsXG4gICAgICogcmV0dXJucyB0aGUgbGF5ZXIgaXRzZWxmLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZCB0aGUgbGF5ZXIncyBpZFxuICAgICAqIEByZXR1cm5zIHtMYXllcn0gdGhlIHJlZmVyZW50IGxheWVyIG9yIHRoZSBsYXllciBpdHNlbGZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldFJlZmVyZW50TGF5ZXI6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoaWQpO1xuICAgICAgICBpZiAobGF5ZXIucmVmKSB7XG4gICAgICAgICAgICBsYXllciA9IHRoaXMuZ2V0TGF5ZXIobGF5ZXIucmVmKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfSxcblxuICAgIHNldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIsIGZpbHRlcikge1xuICAgICAgICBsYXllciA9IHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcik7XG4gICAgICAgIGxheWVyLmZpbHRlciA9IGZpbHRlcjtcbiAgICAgICAgdGhpcy5fYnJvYWRjYXN0TGF5ZXJzKCk7XG4gICAgICAgIHRoaXMuc291cmNlc1tsYXllci5zb3VyY2VdLnJlbG9hZCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsYXllcidzIGZpbHRlciBvYmplY3RcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbGF5ZXIgdGhlIGxheWVyIHRvIGluc3BlY3RcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIGxheWVyJ3MgZmlsdGVyLCBpZiBhbnlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldEZpbHRlcjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZmlsdGVyO1xuICAgIH0sXG5cbiAgICBzZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIGxheWVyID0gdGhpcy5nZXRSZWZlcmVudExheWVyKGxheWVyKTtcbiAgICAgICAgbGF5ZXIuc2V0TGF5b3V0UHJvcGVydHkobmFtZSwgdmFsdWUpO1xuICAgICAgICB0aGlzLl9icm9hZGNhc3RMYXllcnMoKTtcbiAgICAgICAgdGhpcy5zb3VyY2VzW2xheWVyLnNvdXJjZV0ucmVsb2FkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhIGxheW91dCBwcm9wZXJ0eSdzIHZhbHVlIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBsYXllciB0aGUgbGF5ZXIgdG8gaW5zcGVjdFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIHByb3BlcnR5IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmZXJlbnRMYXllcihsYXllcikuZ2V0TGF5b3V0UHJvcGVydHkobmFtZSk7XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSwga2xhc3MpIHtcbiAgICAgICAgdGhpcy5nZXRMYXllcihsYXllcikuc2V0UGFpbnRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihsYXllciwgbmFtZSwga2xhc3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGF5ZXIobGF5ZXIpLmdldFBhaW50UHJvcGVydHkobmFtZSwga2xhc3MpO1xuICAgIH0sXG5cbiAgICBmZWF0dXJlc0F0OiBmdW5jdGlvbihjb29yZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICAgICAgdmFyIGVycm9yID0gbnVsbDtcblxuICAgICAgICBpZiAocGFyYW1zLmxheWVyKSB7XG4gICAgICAgICAgICBwYXJhbXMubGF5ZXIgPSB7IGlkOiBwYXJhbXMubGF5ZXIgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHV0aWwuYXN5bmNFYWNoKE9iamVjdC5rZXlzKHRoaXMuc291cmNlcyksIGZ1bmN0aW9uKGlkLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuc291cmNlc1tpZF07XG4gICAgICAgICAgICBzb3VyY2UuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBmdW5jdGlvbihlcnIsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIGZlYXR1cmVzID0gZmVhdHVyZXMuY29uY2F0KHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycikgZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LmJpbmQodGhpcyksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuXG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBmZWF0dXJlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICBmZWF0dXJlLmxheWVyID0gdGhpcy5fbGF5ZXJzW2ZlYXR1cmUubGF5ZXJdLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZlYXR1cmU7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcblxuICAgIF9yZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXIucmVtb3ZlKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVTb3VyY2VzOiBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZXNbaWRdLnVwZGF0ZSh0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9yZWRvUGxhY2VtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zb3VyY2VzW2lkXS5yZWRvUGxhY2VtZW50KSB0aGlzLnNvdXJjZXNbaWRdLnJlZG9QbGFjZW1lbnQoKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfZm9yd2FyZFNvdXJjZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZSgnc291cmNlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzb3VyY2U6IGUudGFyZ2V0fSwgZSkpO1xuICAgIH0sXG5cbiAgICBfZm9yd2FyZFRpbGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoZS50eXBlLCB1dGlsLmV4dGVuZCh7c291cmNlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgLy8gQ2FsbGJhY2tzIGZyb20gd2ViIHdvcmtlcnNcblxuICAgICdnZXQgc3ByaXRlIGpzb24nOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgeyBzcHJpdGU6IHNwcml0ZS5kYXRhLCByZXRpbmE6IHNwcml0ZS5yZXRpbmEgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzcHJpdGUub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7IHNwcml0ZTogc3ByaXRlLmRhdGEsIHJldGluYTogc3ByaXRlLnJldGluYSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgICdnZXQgaWNvbnMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzcHJpdGUgPSB0aGlzLnNwcml0ZTtcbiAgICAgICAgdmFyIHNwcml0ZUF0bGFzID0gdGhpcy5zcHJpdGVBdGxhcztcbiAgICAgICAgaWYgKHNwcml0ZS5sb2FkZWQoKSkge1xuICAgICAgICAgICAgc3ByaXRlQXRsYXMuc2V0U3ByaXRlKHNwcml0ZSk7XG4gICAgICAgICAgICBzcHJpdGVBdGxhcy5hZGRJY29ucyhwYXJhbXMuaWNvbnMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwcml0ZS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLnNldFNwcml0ZShzcHJpdGUpO1xuICAgICAgICAgICAgICAgIHNwcml0ZUF0bGFzLmFkZEljb25zKHBhcmFtcy5pY29ucywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2dldCBnbHlwaHMnOiBmdW5jdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2x5cGhTb3VyY2UuZ2V0U2ltcGxlR2x5cGhzKHBhcmFtcy5mb250c3RhY2ssIHBhcmFtcy5jb2RlcG9pbnRzLCBwYXJhbXMudWlkLCBjYWxsYmFjayk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmV4cG9ydHMucmVzb2x2ZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb25zdGFudHMpIHtcbiAgICBmdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlWzBdID09PSAnQCcgPyBjb25zdGFudHNbdmFsdWVdIDogdmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIGk7XG5cbiAgICB2YWx1ZSA9IHJlc29sdmUodmFsdWUpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtpXSBpbiBjb25zdGFudHMpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtpXSA9IHJlc29sdmUodmFsdWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHZhbHVlID0gdXRpbC5leHRlbmQoe30sIHZhbHVlKTtcbiAgICAgICAgdmFsdWUuc3RvcHMgPSB2YWx1ZS5zdG9wcy5zbGljZSgpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB2YWx1ZS5zdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHZhbHVlLnN0b3BzW2ldWzFdIGluIGNvbnN0YW50cykge1xuICAgICAgICAgICAgICAgIHZhbHVlLnN0b3BzW2ldID0gW1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zdG9wc1tpXVswXSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS5zdG9wc1tpXVsxXSlcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0cy5yZXNvbHZlQWxsID0gZnVuY3Rpb24gKHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIGlmICghY29uc3RhbnRzKVxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcblxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIGZvciAodmFyIGtleSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gZXhwb3J0cy5yZXNvbHZlKHByb3BlcnRpZXNba2V5XSwgY29uc3RhbnRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhcnNlQ1NTQ29sb3IgPSByZXF1aXJlKCdjc3Njb2xvcnBhcnNlcicpLnBhcnNlQ1NTQ29sb3I7XG52YXIgbWFwYm94R0xGdW5jdGlvbiA9IHJlcXVpcmUoJ21hcGJveC1nbC1mdW5jdGlvbicpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZURlY2xhcmF0aW9uO1xuXG5mdW5jdGlvbiBTdHlsZURlY2xhcmF0aW9uKHJlZmVyZW5jZSwgdmFsdWUpIHtcbiAgICB0aGlzLnR5cGUgPSByZWZlcmVuY2UudHlwZTtcbiAgICB0aGlzLnRyYW5zaXRpb25hYmxlID0gcmVmZXJlbmNlLnRyYW5zaXRpb247XG5cbiAgICAvLyBpbW11dGFibGUgcmVwcmVzZW50YXRpb24gb2YgdmFsdWUuIHVzZWQgZm9yIGNvbXBhcmlzb25cbiAgICB0aGlzLmpzb24gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbiAgICBpZiAodGhpcy50eXBlICE9PSAnY29sb3InKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnN0b3BzKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBwcmVwYXJlQ29sb3JGdW5jdGlvbih2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHBhcnNlQ29sb3IodmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChyZWZlcmVuY2UuZnVuY3Rpb24gPT09ICdpbnRlcnBvbGF0ZWQnKSB7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlID0gbWFwYm94R0xGdW5jdGlvbi5pbnRlcnBvbGF0ZWQodGhpcy52YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jYWxjdWxhdGUgPSBtYXBib3hHTEZ1bmN0aW9uWydwaWVjZXdpc2UtY29uc3RhbnQnXSh0aGlzLnZhbHVlKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZS50cmFuc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZSA9IHRyYW5zaXRpb25lZCh0aGlzLmNhbGN1bGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb25lZChjYWxjdWxhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeiwgemgsIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBmcmFjdGlvbiA9IHogJSAxO1xuICAgICAgICB2YXIgdCA9IE1hdGgubWluKChEYXRlLm5vdygpIC0gemgubGFzdEludGVnZXJab29tVGltZSkgLyBkdXJhdGlvbiwgMSk7XG4gICAgICAgIHZhciBmcm9tU2NhbGUgPSAxO1xuICAgICAgICB2YXIgdG9TY2FsZSA9IDE7XG4gICAgICAgIHZhciBtaXgsIGZyb20sIHRvO1xuXG4gICAgICAgIGlmICh6ID4gemgubGFzdEludGVnZXJab29tKSB7XG4gICAgICAgICAgICBtaXggPSBmcmFjdGlvbiArICgxIC0gZnJhY3Rpb24pICogdDtcbiAgICAgICAgICAgIGZyb21TY2FsZSAqPSAyO1xuICAgICAgICAgICAgZnJvbSA9IGNhbGN1bGF0ZSh6IC0gMSk7XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1peCA9IDEgLSAoMSAtIHQpICogZnJhY3Rpb247XG4gICAgICAgICAgICB0byA9IGNhbGN1bGF0ZSh6KTtcbiAgICAgICAgICAgIGZyb20gPSBjYWxjdWxhdGUoeiArIDEpO1xuICAgICAgICAgICAgZnJvbVNjYWxlIC89IDI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgIGZyb21TY2FsZTogZnJvbVNjYWxlLFxuICAgICAgICAgICAgdG86IHRvLFxuICAgICAgICAgICAgdG9TY2FsZTogdG9TY2FsZSxcbiAgICAgICAgICAgIHQ6IG1peFxuICAgICAgICB9O1xuICAgIH07XG59XG5cbnZhciBjb2xvckNhY2hlID0ge307XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3IodmFsdWUpIHtcbiAgICBpZiAoY29sb3JDYWNoZVt2YWx1ZV0pIHJldHVybiBjb2xvckNhY2hlW3ZhbHVlXTtcbiAgICB2YXIgY29sb3IgPSBwcmVwYXJlQ29sb3IocGFyc2VDU1NDb2xvcih2YWx1ZSkpO1xuICAgIGNvbG9yQ2FjaGVbdmFsdWVdID0gY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3IoYykge1xuICAgIHJldHVybiBbY1swXSAvIDI1NSwgY1sxXSAvIDI1NSwgY1syXSAvIDI1NSwgY1szXSAvIDFdO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29sb3JGdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIHV0aWwuZXh0ZW5kKHt9LCBmLCB7c3RvcHM6IGYuc3RvcHMubWFwKGZ1bmN0aW9uKHN0b3ApIHtcbiAgICAgICAgcmV0dXJuIFtzdG9wWzBdLCBwYXJzZUNvbG9yKHN0b3BbMV0pXTtcbiAgICB9KX0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIHJlZmVyZW5jZSA9IHJlcXVpcmUoJy4vcmVmZXJlbmNlJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbicpO1xuXG52YXIgbG9va3VwID0ge1xuICAgIHBhaW50OiB7fSxcbiAgICBsYXlvdXQ6IHt9XG59O1xuXG5yZWZlcmVuY2UubGF5ZXIudHlwZS52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih0eXBlKSB7XG4gICAgbG9va3VwLnBhaW50W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsncGFpbnRfJyArIHR5cGVdKTtcbiAgICBsb29rdXAubGF5b3V0W3R5cGVdID0gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZVsnbGF5b3V0XycgKyB0eXBlXSk7XG59KTtcblxuZnVuY3Rpb24gbWFrZUNvbnN0cnVjdG9yKHJlZmVyZW5jZSkge1xuICAgIGZ1bmN0aW9uIFN0eWxlRGVjbGFyYXRpb25TZXQocHJvcGVydGllcywgY29uc3RhbnRzKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IHt9O1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9ucyA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2NvbnN0YW50cyA9IGNvbnN0YW50cztcblxuICAgICAgICBmb3IgKHZhciBrIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXNba10gPSBTdHlsZUNvbnN0YW50LnJlc29sdmUocHJvcGVydGllc1trXSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKHJlZmVyZW5jZSkuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgICAgIHZhciBwcm9wZXJ0eSA9IHJlZmVyZW5jZVtrXTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3R5bGVEZWNsYXJhdGlvblNldC5wcm90b3R5cGUsIGssIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlc1trXSA9IG5ldyBTdHlsZURlY2xhcmF0aW9uKHByb3BlcnR5LCBTdHlsZUNvbnN0YW50LnJlc29sdmUodiwgdGhpcy5fY29uc3RhbnRzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzW2tdLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocHJvcGVydHkudHJhbnNpdGlvbikge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLCBrICsgJy10cmFuc2l0aW9uJywge1xuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2l0aW9uc1trXSA9IHY7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNpdGlvbnNba107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVzO1xuICAgIH07XG5cbiAgICBTdHlsZURlY2xhcmF0aW9uU2V0LnByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24oaywgZ2xvYmFsKSB7XG4gICAgICAgIHZhciB0ID0gdGhpcy5fdHJhbnNpdGlvbnNba10gfHwge307XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkdXJhdGlvbjogdXRpbC5jb2FsZXNjZSh0LmR1cmF0aW9uLCBnbG9iYWwuZHVyYXRpb24sIDMwMCksXG4gICAgICAgICAgICBkZWxheTogdXRpbC5jb2FsZXNjZSh0LmRlbGF5LCBnbG9iYWwuZGVsYXksIDApXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIFN0eWxlRGVjbGFyYXRpb25TZXQucHJvdG90eXBlLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgIGZvciAodmFyIHYgaW4gdGhpcy5fdmFsdWVzKSB7XG4gICAgICAgICAgICByZXN1bHRbdl0gPSB0aGlzLl92YWx1ZXNbdl0udmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciB0IGluIHRoaXMuX3RyYW5zaXRpb25zKSB7XG4gICAgICAgICAgICByZXN1bHRbdCArICctdHJhbnNpdGlvbiddID0gdGhpcy5fdHJhbnNpdGlvbnNbdl07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICByZXR1cm4gU3R5bGVEZWNsYXJhdGlvblNldDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihyZW5kZXJUeXBlLCBsYXllclR5cGUsIHByb3BlcnRpZXMsIGNvbnN0YW50cykge1xuICAgIHJldHVybiBuZXcgbG9va3VwW3JlbmRlclR5cGVdW2xheWVyVHlwZV0ocHJvcGVydGllcywgY29uc3RhbnRzKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgU3R5bGVDb25zdGFudCA9IHJlcXVpcmUoJy4vc3R5bGVfY29uc3RhbnQnKTtcbnZhciBTdHlsZVRyYW5zaXRpb24gPSByZXF1aXJlKCcuL3N0eWxlX3RyYW5zaXRpb24nKTtcbnZhciBTdHlsZURlY2xhcmF0aW9uU2V0ID0gcmVxdWlyZSgnLi9zdHlsZV9kZWNsYXJhdGlvbl9zZXQnKTtcbnZhciBMYXlvdXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9sYXlvdXRfcHJvcGVydGllcycpO1xudmFyIFBhaW50UHJvcGVydGllcyA9IHJlcXVpcmUoJy4vcGFpbnRfcHJvcGVydGllcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFN0eWxlTGF5ZXIobGF5ZXIsIGNvbnN0YW50cykge1xuICAgIHRoaXMuX2xheWVyID0gbGF5ZXI7XG4gICAgdGhpcy5fY29uc3RhbnRzID0gY29uc3RhbnRzO1xuXG4gICAgdGhpcy5pZCA9IGxheWVyLmlkO1xuICAgIHRoaXMucmVmID0gbGF5ZXIucmVmO1xuXG4gICAgLy8gUmVzb2x2ZWQgYW5kIGNhc2NhZGVkIHBhaW50IHByb3BlcnRpZXMuXG4gICAgdGhpcy5fcmVzb2x2ZWQgPSB7fTsgLy8gY2xhc3MgbmFtZSAtPiBTdHlsZURlY2xhcmF0aW9uU2V0XG4gICAgdGhpcy5fY2FzY2FkZWQgPSB7fTsgLy8gcHJvcGVydHkgbmFtZSAtPiBTdHlsZVRyYW5zaXRpb25cblxuICAgIHRoaXMuYXNzaWduKGxheWVyKTtcbn1cblxuU3R5bGVMYXllci5wcm90b3R5cGUgPSB7XG4gICAgcmVzb2x2ZUxheW91dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5yZWYpIHtcbiAgICAgICAgICAgIHRoaXMubGF5b3V0ID0gbmV3IExheW91dFByb3BlcnRpZXNbdGhpcy50eXBlXShcbiAgICAgICAgICAgICAgICBTdHlsZUNvbnN0YW50LnJlc29sdmVBbGwodGhpcy5fbGF5ZXIubGF5b3V0LCB0aGlzLl9jb25zdGFudHMpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMubGF5b3V0WydzeW1ib2wtcGxhY2VtZW50J10gPT09ICdsaW5lJykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5sYXlvdXQuaGFzT3duUHJvcGVydHkoJ3RleHQtcm90YXRpb24tYWxpZ25tZW50JykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXRbJ3RleHQtcm90YXRpb24tYWxpZ25tZW50J10gPSAnbWFwJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxheW91dC5oYXNPd25Qcm9wZXJ0eSgnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnQnXSA9ICdtYXAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmxheW91dFsnc3ltYm9sLWF2b2lkLWVkZ2VzJ10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldExheW91dFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmxheW91dFtuYW1lXSA9IFN0eWxlQ29uc3RhbnQucmVzb2x2ZSh2YWx1ZSwgdGhpcy5fY29uc3RhbnRzKTtcbiAgICB9LFxuXG4gICAgZ2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGF5b3V0W25hbWVdO1xuICAgIH0sXG5cbiAgICByZXNvbHZlUmVmZXJlbmNlOiBmdW5jdGlvbihsYXllcnMpIHtcbiAgICAgICAgaWYgKHRoaXMucmVmKSB7XG4gICAgICAgICAgICB0aGlzLmFzc2lnbihsYXllcnNbdGhpcy5yZWZdKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZXNvbHZlUGFpbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBwIGluIHRoaXMuX2xheWVyKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBwLm1hdGNoKC9ecGFpbnQoPzpcXC4oLiopKT8kLyk7XG4gICAgICAgICAgICBpZiAoIW1hdGNoKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgdGhpcy5fcmVzb2x2ZWRbbWF0Y2hbMV0gfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHRoaXMuX2xheWVyW3BdLCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldFBhaW50UHJvcGVydHk6IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucykge1xuICAgICAgICAgICAgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddID1cbiAgICAgICAgICAgICAgICBuZXcgU3R5bGVEZWNsYXJhdGlvblNldCgncGFpbnQnLCB0aGlzLnR5cGUsIHt9LCB0aGlzLl9jb25zdGFudHMpO1xuICAgICAgICB9XG4gICAgICAgIGRlY2xhcmF0aW9uc1tuYW1lXSA9IHZhbHVlO1xuICAgIH0sXG5cbiAgICBnZXRQYWludFByb3BlcnR5OiBmdW5jdGlvbihuYW1lLCBrbGFzcykge1xuICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3MgfHwgJyddO1xuICAgICAgICBpZiAoIWRlY2xhcmF0aW9ucylcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBkZWNsYXJhdGlvbnNbbmFtZV07XG4gICAgfSxcblxuICAgIGNhc2NhZGU6IGZ1bmN0aW9uKGNsYXNzZXMsIG9wdGlvbnMsIGdsb2JhbFRyYW5zLCBhbmltYXRpb25Mb29wKSB7XG4gICAgICAgIGZvciAodmFyIGtsYXNzIGluIHRoaXMuX3Jlc29sdmVkKSB7XG4gICAgICAgICAgICBpZiAoa2xhc3MgIT09IFwiXCIgJiYgIWNsYXNzZXNba2xhc3NdKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgZGVjbGFyYXRpb25zID0gdGhpcy5fcmVzb2x2ZWRba2xhc3NdLFxuICAgICAgICAgICAgICAgIHZhbHVlcyA9IGRlY2xhcmF0aW9ucy52YWx1ZXMoKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgayBpbiB2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RGVjbGFyYXRpb24gPSB2YWx1ZXNba107XG4gICAgICAgICAgICAgICAgdmFyIG9sZFRyYW5zaXRpb24gPSBvcHRpb25zLnRyYW5zaXRpb24gPyB0aGlzLl9jYXNjYWRlZFtrXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IHRyYW5zaXRpb24gaWYgdGhlIGRlY2xhcmF0aW9uIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpZiAoIW9sZFRyYW5zaXRpb24gfHwgb2xkVHJhbnNpdGlvbi5kZWNsYXJhdGlvbi5qc29uICE9PSBuZXdEZWNsYXJhdGlvbi5qc29uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdTdHlsZVRyYW5zID0gZGVjbGFyYXRpb25zLnRyYW5zaXRpb24oaywgZ2xvYmFsVHJhbnMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMuX2Nhc2NhZGVkW2tdID1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTdHlsZVRyYW5zaXRpb24obmV3RGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIG5ld1N0eWxlVHJhbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJ1biB0aGUgYW5pbWF0aW9uIGxvb3AgdW50aWwgdGhlIGVuZCBvZiB0aGUgdHJhbnNpdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld1RyYW5zaXRpb24uaW5zdGFudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdUcmFuc2l0aW9uLmxvb3BJRCA9IGFuaW1hdGlvbkxvb3Auc2V0KG5ld1RyYW5zaXRpb24uZW5kVGltZSAtIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkxvb3AuY2FuY2VsKG9sZFRyYW5zaXRpb24ubG9vcElEKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZWNhbGN1bGF0ZTogZnVuY3Rpb24oeiwgem9vbUhpc3RvcnkpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLnR5cGUsXG4gICAgICAgICAgICBjYWxjdWxhdGVkID0gdGhpcy5wYWludCA9IG5ldyBQYWludFByb3BlcnRpZXNbdHlwZV0oKTtcblxuICAgICAgICBmb3IgKHZhciBrIGluIHRoaXMuX2Nhc2NhZGVkKSB7XG4gICAgICAgICAgICBjYWxjdWxhdGVkW2tdID0gdGhpcy5fY2FzY2FkZWRba10uYXQoeiwgem9vbUhpc3RvcnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRkZW4gPSAodGhpcy5taW56b29tICYmIHogPCB0aGlzLm1pbnpvb20pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKHRoaXMubWF4em9vbSAmJiB6ID49IHRoaXMubWF4em9vbSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpbmNsdWRlIHZpc2liaWxpdHkgY2hlY2sgZm9yIG5vbi1idWNrZXRlZCBiYWNrZ3JvdW5kIGxheWVyc1xuICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmxheW91dC52aXNpYmlsaXR5ID09PSAnbm9uZScpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgICAgaWYgKChjYWxjdWxhdGVkWyd0ZXh0LW9wYWNpdHknXSA9PT0gMCB8fCAhdGhpcy5sYXlvdXRbJ3RleHQtZmllbGQnXSkgJiZcbiAgICAgICAgICAgICAgICAoY2FsY3VsYXRlZFsnaWNvbi1vcGFjaXR5J10gPT09IDAgfHwgIXRoaXMubGF5b3V0WydpY29uLWltYWdlJ10pKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVtdWx0aXBseUxheWVyKGNhbGN1bGF0ZWQsICd0ZXh0Jyk7XG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbHlMYXllcihjYWxjdWxhdGVkLCAnaWNvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoY2FsY3VsYXRlZFt0eXBlICsgJy1vcGFjaXR5J10gPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZW11bHRpcGx5TGF5ZXIoY2FsY3VsYXRlZCwgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY2FzY2FkZWRbJ2xpbmUtZGFzaGFycmF5J10pIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBsaW5lIGlzIGRhc2hlZCwgc2NhbGUgdGhlIGRhc2ggbGVuZ3RocyBieSB0aGUgbGluZVxuICAgICAgICAgICAgLy8gd2lkdGggYXQgdGhlIHByZXZpb3VzIHJvdW5kIHpvb20gbGV2ZWwuXG4gICAgICAgICAgICB2YXIgZGFzaEFycmF5ID0gY2FsY3VsYXRlZFsnbGluZS1kYXNoYXJyYXknXTtcbiAgICAgICAgICAgIHZhciBsaW5lV2lkdGggPSB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddID9cbiAgICAgICAgICAgICAgICB0aGlzLl9jYXNjYWRlZFsnbGluZS13aWR0aCddLmF0KE1hdGguZmxvb3IoeiksIEluZmluaXR5KSA6XG4gICAgICAgICAgICAgICAgY2FsY3VsYXRlZFsnbGluZS13aWR0aCddO1xuXG4gICAgICAgICAgICBkYXNoQXJyYXkuZnJvbVNjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgICAgIGRhc2hBcnJheS50b1NjYWxlICo9IGxpbmVXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhdGhpcy5oaWRkZW47XG4gICAgfSxcblxuICAgIGFzc2lnbjogZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgdXRpbC5leHRlbmQodGhpcywgdXRpbC5waWNrKGxheWVyLFxuICAgICAgICAgICAgWyd0eXBlJywgJ3NvdXJjZScsICdzb3VyY2UtbGF5ZXInLFxuICAgICAgICAgICAgJ21pbnpvb20nLCAnbWF4em9vbScsICdmaWx0ZXInLFxuICAgICAgICAgICAgJ2xheW91dCddKSk7XG4gICAgfSxcblxuICAgIGpzb246IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdXRpbC5leHRlbmQoe30sXG4gICAgICAgICAgICB0aGlzLl9sYXllcixcbiAgICAgICAgICAgIHV0aWwucGljayh0aGlzLFxuICAgICAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJyxcbiAgICAgICAgICAgICAgICAnbWluem9vbScsICdtYXh6b29tJywgJ2ZpbHRlcicsXG4gICAgICAgICAgICAgICAgJ2xheW91dCcsICdwYWludCddKSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcHJlbXVsdGlwbHlMYXllcihsYXllciwgdHlwZSkge1xuICAgIHZhciBjb2xvclByb3AgPSB0eXBlICsgJy1jb2xvcicsXG4gICAgICAgIGhhbG9Qcm9wID0gdHlwZSArICctaGFsby1jb2xvcicsXG4gICAgICAgIG91dGxpbmVQcm9wID0gdHlwZSArICctb3V0bGluZS1jb2xvcicsXG4gICAgICAgIGNvbG9yID0gbGF5ZXJbY29sb3JQcm9wXSxcbiAgICAgICAgaGFsb0NvbG9yID0gbGF5ZXJbaGFsb1Byb3BdLFxuICAgICAgICBvdXRsaW5lQ29sb3IgPSBsYXllcltvdXRsaW5lUHJvcF0sXG4gICAgICAgIG9wYWNpdHkgPSBsYXllclt0eXBlICsgJy1vcGFjaXR5J107XG5cbiAgICB2YXIgY29sb3JPcGFjaXR5ID0gY29sb3IgJiYgKG9wYWNpdHkgKiBjb2xvclszXSk7XG4gICAgdmFyIGhhbG9PcGFjaXR5ID0gaGFsb0NvbG9yICYmIChvcGFjaXR5ICogaGFsb0NvbG9yWzNdKTtcbiAgICB2YXIgb3V0bGluZU9wYWNpdHkgPSBvdXRsaW5lQ29sb3IgJiYgKG9wYWNpdHkgKiBvdXRsaW5lQ29sb3JbM10pO1xuXG4gICAgaWYgKGNvbG9yT3BhY2l0eSAhPT0gdW5kZWZpbmVkICYmIGNvbG9yT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbY29sb3JQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW2NvbG9yWzBdLCBjb2xvclsxXSwgY29sb3JbMl0sIGNvbG9yT3BhY2l0eV0pO1xuICAgIH1cbiAgICBpZiAoaGFsb09wYWNpdHkgIT09IHVuZGVmaW5lZCAmJiBoYWxvT3BhY2l0eSA8IDEpIHtcbiAgICAgICAgbGF5ZXJbaGFsb1Byb3BdID0gdXRpbC5wcmVtdWx0aXBseShbaGFsb0NvbG9yWzBdLCBoYWxvQ29sb3JbMV0sIGhhbG9Db2xvclsyXSwgaGFsb09wYWNpdHldKTtcbiAgICB9XG4gICAgaWYgKG91dGxpbmVPcGFjaXR5ICE9PSB1bmRlZmluZWQgJiYgb3V0bGluZU9wYWNpdHkgPCAxKSB7XG4gICAgICAgIGxheWVyW291dGxpbmVQcm9wXSA9IHV0aWwucHJlbXVsdGlwbHkoW291dGxpbmVDb2xvclswXSwgb3V0bGluZUNvbG9yWzFdLCBvdXRsaW5lQ29sb3JbMl0sIG91dGxpbmVPcGFjaXR5XSk7XG4gICAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0eWxlVHJhbnNpdGlvbjtcblxuLypcbiAqIFJlcHJlc2VudHMgYSB0cmFuc2l0aW9uIGJldHdlZW4gdHdvIGRlY2xhcmF0aW9uc1xuICovXG5mdW5jdGlvbiBTdHlsZVRyYW5zaXRpb24oZGVjbGFyYXRpb24sIG9sZFRyYW5zaXRpb24sIHZhbHVlKSB7XG5cbiAgICB0aGlzLmRlY2xhcmF0aW9uID0gZGVjbGFyYXRpb247XG4gICAgdGhpcy5zdGFydFRpbWUgPSB0aGlzLmVuZFRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuXG4gICAgdmFyIHR5cGUgPSBkZWNsYXJhdGlvbi50eXBlO1xuICAgIGlmICgodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ2FycmF5JykgJiYgZGVjbGFyYXRpb24udHJhbnNpdGlvbmFibGUpIHtcbiAgICAgICAgdGhpcy5pbnRlcnAgPSBpbnRlcnBab29tVHJhbnNpdGlvbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW50ZXJwID0gaW50ZXJwb2xhdGVbdHlwZV07XG4gICAgfVxuXG4gICAgdGhpcy5vbGRUcmFuc2l0aW9uID0gb2xkVHJhbnNpdGlvbjtcbiAgICB0aGlzLmR1cmF0aW9uID0gdmFsdWUuZHVyYXRpb24gfHwgMDtcbiAgICB0aGlzLmRlbGF5ID0gdmFsdWUuZGVsYXkgfHwgMDtcblxuICAgIGlmICghdGhpcy5pbnN0YW50KCkpIHtcbiAgICAgICAgdGhpcy5lbmRUaW1lID0gdGhpcy5zdGFydFRpbWUgKyB0aGlzLmR1cmF0aW9uICsgdGhpcy5kZWxheTtcbiAgICAgICAgdGhpcy5lYXNlID0gdXRpbC5lYXNlQ3ViaWNJbk91dDtcbiAgICB9XG5cbiAgICBpZiAob2xkVHJhbnNpdGlvbiAmJiBvbGRUcmFuc2l0aW9uLmVuZFRpbWUgPD0gdGhpcy5zdGFydFRpbWUpIHtcbiAgICAgICAgLy8gT2xkIHRyYW5zaXRpb24gaXMgZG9uZSBydW5uaW5nLCBzbyB3ZSBjYW5cbiAgICAgICAgLy8gZGVsZXRlIGl0cyByZWZlcmVuY2UgdG8gaXRzIG9sZCB0cmFuc2l0aW9uLlxuXG4gICAgICAgIGRlbGV0ZSBvbGRUcmFuc2l0aW9uLm9sZFRyYW5zaXRpb247XG4gICAgfVxufVxuXG5TdHlsZVRyYW5zaXRpb24ucHJvdG90eXBlLmluc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMub2xkVHJhbnNpdGlvbiB8fCAhdGhpcy5pbnRlcnAgfHwgKHRoaXMuZHVyYXRpb24gPT09IDAgJiYgdGhpcy5kZWxheSA9PT0gMCk7XG59O1xuXG4vKlxuICogUmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgdHJhbnNpdGlvbmluZyBwcm9wZXJ0eSBhdCB6b29tIGxldmVsIGB6YCBhbmQgb3B0aW9uYWwgdGltZSBgdGBcbiAqL1xuU3R5bGVUcmFuc2l0aW9uLnByb3RvdHlwZS5hdCA9IGZ1bmN0aW9uKHosIHpvb21IaXN0b3J5LCB0KSB7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLmRlY2xhcmF0aW9uLmNhbGN1bGF0ZSh6LCB6b29tSGlzdG9yeSwgdGhpcy5kdXJhdGlvbik7XG5cbiAgICBpZiAodGhpcy5pbnN0YW50KCkpIHJldHVybiB2YWx1ZTtcblxuICAgIHQgPSB0IHx8IERhdGUubm93KCk7XG5cbiAgICBpZiAodCA8IHRoaXMuZW5kVGltZSkge1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm9sZFRyYW5zaXRpb24uYXQoeiwgem9vbUhpc3RvcnksIHRoaXMuc3RhcnRUaW1lKTtcbiAgICAgICAgdmFyIGVhc2VkID0gdGhpcy5lYXNlKCh0IC0gdGhpcy5zdGFydFRpbWUgLSB0aGlzLmRlbGF5KSAvIHRoaXMuZHVyYXRpb24pO1xuICAgICAgICB2YWx1ZSA9IHRoaXMuaW50ZXJwKG9sZFZhbHVlLCB2YWx1ZSwgZWFzZWQpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcblxufTtcblxuZnVuY3Rpb24gaW50ZXJwWm9vbVRyYW5zaXRpb25lZChmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGZyb20udG8sXG4gICAgICAgIGZyb21TY2FsZTogZnJvbS50b1NjYWxlLFxuICAgICAgICB0bzogdG8udG8sXG4gICAgICAgIHRvU2NhbGU6IHRvLnRvU2NhbGUsXG4gICAgICAgIHQ6IHRcbiAgICB9O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuY2hvcjtcblxuZnVuY3Rpb24gQW5jaG9yKHgsIHksIGFuZ2xlLCBzZWdtZW50KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xuICAgIHRoaXMuYW5nbGUgPSBhbmdsZTtcblxuICAgIGlmIChzZWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDtcbiAgICB9XG59XG5cbkFuY2hvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBvaW50LnByb3RvdHlwZSk7XG5cbkFuY2hvci5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IEFuY2hvcih0aGlzLngsIHRoaXMueSwgdGhpcy5hbmdsZSwgdGhpcy5zZWdtZW50KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gQmluUGFjaztcbmZ1bmN0aW9uIEJpblBhY2sod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLmZyZWUgPSBbeyB4OiAwLCB5OiAwLCB3OiB3aWR0aCwgaDogaGVpZ2h0IH1dO1xufVxuXG4vKipcbiAqIFNpbXBsZSBhbGdvcml0aG0gdG8gcmVjdXJzaXZlbHkgbWVyZ2UgdGhlIG5ld2x5IHJlbGVhc2VkIGNlbGwgd2l0aCBpdHNcbiAqIG5laWdoYm9yLiBUaGlzIGRvZXNuJ3QgbWVyZ2UgbW9yZSB0aGFuIHR3byBjZWxscyBhdCBhIHRpbWUsIGFuZCBmYWlsc1xuICogZm9yIGNvbXBsaWNhdGVkIG1lcmdlcy5cbiAqIEBwcml2YXRlXG4gKi9cbkJpblBhY2sucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbihyZWN0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmZyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmZyZWVbaV07XG5cbiAgICAgICAgaWYgKGZyZWUueSA9PT0gcmVjdC55ICYmIGZyZWUuaCA9PT0gcmVjdC5oICYmIGZyZWUueCArIGZyZWUudyA9PT0gcmVjdC54KSB7XG4gICAgICAgICAgICBmcmVlLncgKz0gcmVjdC53O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZnJlZS54ID09PSByZWN0LnggJiYgZnJlZS53ID09PSByZWN0LncgJiYgZnJlZS55ICsgZnJlZS5oID09PSByZWN0LnkpIHtcbiAgICAgICAgICAgIGZyZWUuaCArPSByZWN0Lmg7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWN0LnkgPT09IGZyZWUueSAmJiByZWN0LmggPT09IGZyZWUuaCAmJiByZWN0LnggKyByZWN0LncgPT09IGZyZWUueCkge1xuICAgICAgICAgICAgZnJlZS54ID0gcmVjdC54O1xuICAgICAgICAgICAgZnJlZS53ICs9IHJlY3QudztcblxuICAgICAgICB9IGVsc2UgaWYgKHJlY3QueCA9PT0gZnJlZS54ICYmIHJlY3QudyA9PT0gZnJlZS53ICYmIHJlY3QueSArIHJlY3QuaCA9PT0gZnJlZS55KSB7XG4gICAgICAgICAgICBmcmVlLnkgPSByZWN0Lnk7XG4gICAgICAgICAgICBmcmVlLmggKz0gcmVjdC5oO1xuXG4gICAgICAgIH0gZWxzZSBjb250aW51ZTtcblxuICAgICAgICB0aGlzLmZyZWUuc3BsaWNlKGksIDEpO1xuICAgICAgICB0aGlzLnJlbGVhc2UoZnJlZSk7XG4gICAgICAgIHJldHVybjtcblxuICAgIH1cbiAgICB0aGlzLmZyZWUucHVzaChyZWN0KTtcbn07XG5cbkJpblBhY2sucHJvdG90eXBlLmFsbG9jYXRlID0gZnVuY3Rpb24od2lkdGgsIGhlaWdodCkge1xuICAgIC8vIEZpbmQgdGhlIHNtYWxsZXN0IGZyZWUgcmVjdCBhbmdsZVxuICAgIHZhciByZWN0ID0geyB4OiBJbmZpbml0eSwgeTogSW5maW5pdHksIHc6IEluZmluaXR5LCBoOiBJbmZpbml0eSB9O1xuICAgIHZhciBzbWFsbGVzdCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZWYgPSB0aGlzLmZyZWVbaV07XG4gICAgICAgIGlmICh3aWR0aCA8PSByZWYudyAmJiBoZWlnaHQgPD0gcmVmLmggJiYgcmVmLnkgPD0gcmVjdC55ICYmIHJlZi54IDw9IHJlY3QueCkge1xuICAgICAgICAgICAgcmVjdCA9IHJlZjtcbiAgICAgICAgICAgIHNtYWxsZXN0ID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzbWFsbGVzdCA8IDApIHtcbiAgICAgICAgLy8gVGhlcmUncyBubyBzcGFjZSBsZWZ0IGZvciB0aGlzIGNoYXIuXG4gICAgICAgIHJldHVybiB7IHg6IC0xLCB5OiAtMSB9O1xuICAgIH1cblxuICAgIHRoaXMuZnJlZS5zcGxpY2Uoc21hbGxlc3QsIDEpO1xuXG4gICAgLy8gU2hvcnRlci9Mb25nZXIgQXhpcyBTcGxpdCBSdWxlIChTQVMpXG4gICAgLy8gaHR0cDovL2NsYi5kZW1vbi5maS9maWxlcy9SZWN0YW5nbGVCaW5QYWNrLnBkZiBwLiAxNVxuICAgIC8vIElnbm9yZSB0aGUgZGltZW5zaW9uIG9mIFIgYW5kIGp1c3Qgc3BsaXQgbG9uZyB0aGUgc2hvcnRlciBkaW1lbnNpb25cbiAgICAvLyBTZWUgQWxzbzogaHR0cDovL3d3dy5jcy5wcmluY2V0b24uZWR1L35jaGF6ZWxsZS9wdWJzL2JsYmlucGFja2luZy5wZGZcbiAgICBpZiAocmVjdC53IDwgcmVjdC5oKSB7XG4gICAgICAgIC8vIHNwbGl0IGhvcml6b250YWxseVxuICAgICAgICAvLyArLS0rLS0tK1xuICAgICAgICAvLyB8X198X19ffCAgPC0tIGIxXG4gICAgICAgIC8vICstLS0tLS0rICA8LS0gYjJcbiAgICAgICAgaWYgKHJlY3QudyA+IHdpZHRoKSB0aGlzLmZyZWUucHVzaCh7IHg6IHJlY3QueCArIHdpZHRoLCB5OiByZWN0LnksIHc6IHJlY3QudyAtIHdpZHRoLCBoOiBoZWlnaHQgfSk7XG4gICAgICAgIGlmIChyZWN0LmggPiBoZWlnaHQpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54LCB5OiByZWN0LnkgKyBoZWlnaHQsIHc6IHJlY3QudywgaDogcmVjdC5oIC0gaGVpZ2h0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNwbGl0IHZlcnRpY2FsbHlcbiAgICAgICAgLy8gKy0tKy0tLStcbiAgICAgICAgLy8gfF9ffCAgIHwgPC0tIGIxXG4gICAgICAgIC8vICstLXwtLS0rIDwtLSBiMlxuICAgICAgICBpZiAocmVjdC53ID4gd2lkdGgpIHRoaXMuZnJlZS5wdXNoKHsgeDogcmVjdC54ICsgd2lkdGgsIHk6IHJlY3QueSwgdzogcmVjdC53IC0gd2lkdGgsIGg6IHJlY3QuaCB9KTtcbiAgICAgICAgaWYgKHJlY3QuaCA+IGhlaWdodCkgdGhpcy5mcmVlLnB1c2goeyB4OiByZWN0LngsIHk6IHJlY3QueSArIGhlaWdodCwgdzogd2lkdGgsIGg6IHJlY3QuaCAtIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB4OiByZWN0LngsIHk6IHJlY3QueSwgdzogd2lkdGgsIGg6IGhlaWdodCB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjaGVja01heEFuZ2xlO1xuXG5mdW5jdGlvbiBjaGVja01heEFuZ2xlKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIHdpbmRvd1NpemUsIG1heEFuZ2xlKSB7XG5cbiAgICAvLyBob3Jpem9udGFsIGxhYmVscyBhbHdheXMgcGFzc1xuICAgIGlmIChhbmNob3Iuc2VnbWVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBwID0gYW5jaG9yO1xuICAgIHZhciBpbmRleCA9IGFuY2hvci5zZWdtZW50ICsgMTtcbiAgICB2YXIgYW5jaG9yRGlzdGFuY2UgPSAwO1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPiAtbGFiZWxMZW5ndGggLyAyKSB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIGlmIChpbmRleCA8IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICBhbmNob3JEaXN0YW5jZSAtPSBsaW5lW2luZGV4XS5kaXN0KHApO1xuICAgICAgICBwID0gbGluZVtpbmRleF07XG4gICAgfVxuXG4gICAgYW5jaG9yRGlzdGFuY2UgKz0gbGluZVtpbmRleF0uZGlzdChsaW5lW2luZGV4ICsgMV0pO1xuICAgIGluZGV4Kys7XG5cbiAgICAvLyBzdG9yZSByZWNlbnQgY29ybmVycyBhbmQgdGhlaXIgdG90YWwgYW5nbGUgZGlmZmVyZW5jZVxuICAgIHZhciByZWNlbnRDb3JuZXJzID0gW107XG4gICAgdmFyIHJlY2VudEFuZ2xlRGVsdGEgPSAwO1xuXG4gICAgLy8gbW92ZSBmb3J3YXJkcyBieSB0aGUgbGVuZ3RoIG9mIHRoZSBsYWJlbCBhbmQgY2hlY2sgYW5nbGVzIGFsb25nIHRoZSB3YXlcbiAgICB3aGlsZSAoYW5jaG9yRGlzdGFuY2UgPCBsYWJlbExlbmd0aCAvIDIpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2luZGV4IC0gMV07XG4gICAgICAgIHZhciBjdXJyZW50ID0gbGluZVtpbmRleF07XG4gICAgICAgIHZhciBuZXh0ID0gbGluZVtpbmRleCArIDFdO1xuXG4gICAgICAgIC8vIHRoZXJlIGlzbid0IGVub3VnaCByb29tIGZvciB0aGUgbGFiZWwgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGxpbmVcbiAgICAgICAgaWYgKCFuZXh0KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIGFuZ2xlRGVsdGEgPSBwcmV2LmFuZ2xlVG8oY3VycmVudCkgLSBjdXJyZW50LmFuZ2xlVG8obmV4dCk7XG4gICAgICAgIC8vIHJlc3RyaWN0IGFuZ2xlIHRvIC1waS4ucGkgcmFuZ2VcbiAgICAgICAgYW5nbGVEZWx0YSA9ICgoYW5nbGVEZWx0YSArIDMgKiBNYXRoLlBJKSAlIChNYXRoLlBJICogMikpIC0gTWF0aC5QSTtcblxuICAgICAgICByZWNlbnRDb3JuZXJzLnB1c2goe1xuICAgICAgICAgICAgZGlzdGFuY2U6IGFuY2hvckRpc3RhbmNlLFxuICAgICAgICAgICAgYW5nbGVEZWx0YTogYW5nbGVEZWx0YVxuICAgICAgICB9KTtcbiAgICAgICAgcmVjZW50QW5nbGVEZWx0YSArPSBhbmdsZURlbHRhO1xuXG4gICAgICAgIC8vIHJlbW92ZSBjb3JuZXJzIHRoYXQgYXJlIGZhciBlbm91Z2ggYXdheSBmcm9tIHRoZSBsaXN0IG9mIHJlY2VudCBhbmNob3JzXG4gICAgICAgIHdoaWxlIChhbmNob3JEaXN0YW5jZSAtIHJlY2VudENvcm5lcnNbMF0uZGlzdGFuY2UgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICByZWNlbnRBbmdsZURlbHRhIC09IHJlY2VudENvcm5lcnMuc2hpZnQoKS5hbmdsZURlbHRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHN1bSBvZiBhbmdsZXMgd2l0aGluIHRoZSB3aW5kb3cgYXJlYSBleGNlZWRzIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuIGNoZWNrIGZhaWxzLlxuICAgICAgICBpZiAoTWF0aC5hYnMocmVjZW50QW5nbGVEZWx0YSkgPiBtYXhBbmdsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGluZGV4Kys7XG4gICAgICAgIGFuY2hvckRpc3RhbmNlICs9IGN1cnJlbnQuZGlzdChuZXh0KTtcbiAgICB9XG5cbiAgICAvLyBubyBwYXJ0IG9mIHRoZSBsaW5lIGhhZCBhbiBhbmdsZSBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gYWxsb3dlZC4gY2hlY2sgcGFzc2VzLlxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUG9pbnQgPSByZXF1aXJlKCdwb2ludC1nZW9tZXRyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsaXBMaW5lO1xuXG5mdW5jdGlvbiBjbGlwTGluZShsaW5lcywgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICB2YXIgY2xpcHBlZExpbmVzID0gW107XG5cbiAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxpbmVzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgIHZhciBsaW5lID0gbGluZXNbbF07XG4gICAgICAgIHZhciBjbGlwcGVkTGluZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmUubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcDAgPSBsaW5lW2ldO1xuICAgICAgICAgICAgdmFyIHAxID0gbGluZVtpICsgMV07XG5cblxuICAgICAgICAgICAgaWYgKHAwLnggPCB4MSAmJiBwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueCA8IHgxKSB7XG4gICAgICAgICAgICAgICAgcDAgPSBuZXcgUG9pbnQoeDEsIHAwLnkgKyAocDEueSAtIHAwLnkpICogKCh4MSAtIHAwLngpIC8gKHAxLnggLSBwMC54KSkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwMS54IDwgeDEpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MSwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgxIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55IDwgeTEgJiYgcDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnkgPCB5MSkge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MSAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA8IHkxKSB7XG4gICAgICAgICAgICAgICAgcDEgPSBuZXcgUG9pbnQocDAueCArIChwMS54IC0gcDAueCkgKiAoKHkxIC0gcDAueSkgLyAocDEueSAtIHAwLnkpKSwgeTEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocDAueCA+PSB4MiAmJiBwMS54ID49IHgyKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAwLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMCA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAxLnggPj0geDIpIHtcbiAgICAgICAgICAgICAgICBwMSA9IG5ldyBQb2ludCh4MiwgcDAueSArIChwMS55IC0gcDAueSkgKiAoKHgyIC0gcDAueCkgLyAocDEueCAtIHAwLngpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwMC55ID49IHkyICYmIHAxLnkgPj0geTIpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDAueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAwID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDEueSA+PSB5Mikge1xuICAgICAgICAgICAgICAgIHAxID0gbmV3IFBvaW50KHAwLnggKyAocDEueCAtIHAwLngpICogKCh5MiAtIHAwLnkpIC8gKHAxLnkgLSBwMC55KSksIHkyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFjbGlwcGVkTGluZSB8fCAhcDAuZXF1YWxzKGNsaXBwZWRMaW5lW2NsaXBwZWRMaW5lLmxlbmd0aCAtIDFdKSkge1xuICAgICAgICAgICAgICAgIGNsaXBwZWRMaW5lID0gW3AwXTtcbiAgICAgICAgICAgICAgICBjbGlwcGVkTGluZXMucHVzaChjbGlwcGVkTGluZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNsaXBwZWRMaW5lLnB1c2gocDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWRMaW5lcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xsaXNpb25Cb3g7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkJveChhbmNob3IsIHgxLCB5MSwgeDIsIHkyLCBtYXhTY2FsZSkge1xuICAgIC8vIHRoZSBib3ggaXMgY2VudGVyZWQgYXJvdW5kIHRoZSBhbmNob3IgcG9pbnRcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcblxuICAgIC8vIGRpc3RhbmNlcyB0byB0aGUgZWRnZXMgZnJvbSB0aGUgYW5jaG9yXG4gICAgdGhpcy54MSA9IHgxO1xuICAgIHRoaXMueTEgPSB5MTtcbiAgICB0aGlzLngyID0geDI7XG4gICAgdGhpcy55MiA9IHkyO1xuXG4gICAgLy8gdGhlIGJveCBpcyBvbmx5IHZhbGlkIGZvciBzY2FsZXMgPCBtYXhTY2FsZS5cbiAgICAvLyBUaGUgYm94IGRvZXMgbm90IGJsb2NrIG90aGVyIGJveGVzIGF0IHNjYWxlcyA+PSBtYXhTY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG5cbiAgICAvLyB0aGUgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIGNhbiBmaXJzdCBiZSBzaG93blxuICAgIHRoaXMucGxhY2VtZW50U2NhbGUgPSAwO1xuXG4gICAgLy8gcm90YXRlZCBhbmQgc2NhbGVkIGJib3ggdXNlZCBmb3IgaW5kZXhpbmdcbiAgICB0aGlzWzBdID0gdGhpc1sxXSA9IHRoaXNbMl0gPSB0aGlzWzNdID0gMDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbGxpc2lvbkJveCA9IHJlcXVpcmUoJy4vY29sbGlzaW9uX2JveCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxpc2lvbkZlYXR1cmU7XG5cbmZ1bmN0aW9uIENvbGxpc2lvbkZlYXR1cmUobGluZSwgYW5jaG9yLCBzaGFwZWQsIGJveFNjYWxlLCBwYWRkaW5nLCBhbGlnbkxpbmUpIHtcblxuICAgIHZhciB5MSA9IHNoYXBlZC50b3AgKiBib3hTY2FsZSAtIHBhZGRpbmc7XG4gICAgdmFyIHkyID0gc2hhcGVkLmJvdHRvbSAqIGJveFNjYWxlICsgcGFkZGluZztcbiAgICB2YXIgeDEgPSBzaGFwZWQubGVmdCAqIGJveFNjYWxlIC0gcGFkZGluZztcbiAgICB2YXIgeDIgPSBzaGFwZWQucmlnaHQgKiBib3hTY2FsZSArIHBhZGRpbmc7XG5cbiAgICB0aGlzLmJveGVzID0gW107XG5cbiAgICBpZiAoYWxpZ25MaW5lKSB7XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IHkyIC0geTE7XG4gICAgICAgIHZhciBsZW5ndGggPSB4MiAtIHgxO1xuXG4gICAgICAgIGlmIChoZWlnaHQgPD0gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIHNldCBtaW5pbXVtIGJveCBoZWlnaHQgdG8gYXZvaWQgdmVyeSBtYW55IHNtYWxsIGxhYmVsc1xuICAgICAgICBoZWlnaHQgPSBNYXRoLm1heCgxMCAqIGJveFNjYWxlLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuYmJveGlmeUxhYmVsKGxpbmUsIGFuY2hvciwgbGVuZ3RoLCBoZWlnaHQpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ib3hlcy5wdXNoKG5ldyBDb2xsaXNpb25Cb3goYW5jaG9yLCB4MSwgeTEsIHgyLCB5MiwgSW5maW5pdHkpKTtcbiAgICB9XG59XG5cbkNvbGxpc2lvbkZlYXR1cmUucHJvdG90eXBlLmJib3hpZnlMYWJlbCA9IGZ1bmN0aW9uKGxpbmUsIGFuY2hvciwgbGFiZWxMZW5ndGgsIGJveFNpemUpIHtcbiAgICB2YXIgc3RlcCA9IGJveFNpemUgLyAyO1xuICAgIHZhciBuQm94ZXMgPSBNYXRoLmZsb29yKGxhYmVsTGVuZ3RoIC8gc3RlcCk7XG5cbiAgICAvLyBvZmZzZXQgdGhlIGNlbnRlciBvZiB0aGUgZmlyc3QgYm94IGJ5IGhhbGYgYSBib3ggc28gdGhhdCB0aGUgZWRnZSBvZiB0aGVcbiAgICAvLyBib3ggaXMgYXQgdGhlIGVkZ2Ugb2YgdGhlIGxhYmVsLlxuICAgIHZhciBmaXJzdEJveE9mZnNldCA9IC1ib3hTaXplIC8gMjtcblxuICAgIHZhciBiYm94ZXMgPSB0aGlzLmJveGVzO1xuXG4gICAgdmFyIHAgPSBhbmNob3I7XG4gICAgdmFyIGluZGV4ID0gYW5jaG9yLnNlZ21lbnQgKyAxO1xuICAgIHZhciBhbmNob3JEaXN0YW5jZSA9IGZpcnN0Qm94T2Zmc2V0O1xuXG4gICAgLy8gbW92ZSBiYWNrd2FyZHMgYWxvbmcgdGhlIGxpbmUgdG8gdGhlIGZpcnN0IHNlZ21lbnQgdGhlIGxhYmVsIGFwcGVhcnMgb25cbiAgICBkbyB7XG4gICAgICAgIGluZGV4LS07XG5cbiAgICAgICAgLy8gdGhlcmUgaXNuJ3QgZW5vdWdoIHJvb20gZm9yIHRoZSBsYWJlbCBhZnRlciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAgIC8vIGNoZWNrTWF4QW5nbGUgc2hvdWxkIGhhdmUgYWxyZWFkeSBjYXVnaHQgdGhpc1xuICAgICAgICBpZiAoaW5kZXggPCAwKSByZXR1cm4gYmJveGVzO1xuXG4gICAgICAgIGFuY2hvckRpc3RhbmNlIC09IGxpbmVbaW5kZXhdLmRpc3QocCk7XG4gICAgICAgIHAgPSBsaW5lW2luZGV4XTtcbiAgICB9IHdoaWxlIChhbmNob3JEaXN0YW5jZSA+IC1sYWJlbExlbmd0aCAvIDIpO1xuXG4gICAgdmFyIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5Cb3hlczsgaSsrKSB7XG4gICAgICAgIC8vIHRoZSBkaXN0YW5jZSB0aGUgYm94IHdpbGwgYmUgZnJvbSB0aGUgYW5jaG9yXG4gICAgICAgIHZhciBib3hEaXN0YW5jZVRvQW5jaG9yID0gLWxhYmVsTGVuZ3RoIC8gMiArIGkgKiBzdGVwO1xuXG4gICAgICAgIC8vIHRoZSBib3ggaXMgbm90IG9uIHRoZSBjdXJyZW50IHNlZ21lbnQuIE1vdmUgdG8gdGhlIG5leHQgc2VnbWVudC5cbiAgICAgICAgd2hpbGUgKGFuY2hvckRpc3RhbmNlICsgc2VnbWVudExlbmd0aCA8IGJveERpc3RhbmNlVG9BbmNob3IpIHtcbiAgICAgICAgICAgIGFuY2hvckRpc3RhbmNlICs9IHNlZ21lbnRMZW5ndGg7XG4gICAgICAgICAgICBpbmRleCsrO1xuXG4gICAgICAgICAgICAvLyBUaGVyZSBpc24ndCBlbm91Z2ggcm9vbSBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgbGluZS5cbiAgICAgICAgICAgIGlmIChpbmRleCArIDEgPj0gbGluZS5sZW5ndGgpIHJldHVybiBiYm94ZXM7XG5cbiAgICAgICAgICAgIHNlZ21lbnRMZW5ndGggPSBsaW5lW2luZGV4XS5kaXN0KGxpbmVbaW5kZXggKyAxXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgZGlzdGFuY2UgdGhlIGJveCB3aWxsIGJlIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc2VnbWVudFxuICAgICAgICB2YXIgc2VnbWVudEJveERpc3RhbmNlID0gYm94RGlzdGFuY2VUb0FuY2hvciAtIGFuY2hvckRpc3RhbmNlO1xuXG4gICAgICAgIHZhciBwMCA9IGxpbmVbaW5kZXhdO1xuICAgICAgICB2YXIgcDEgPSBsaW5lW2luZGV4ICsgMV07XG4gICAgICAgIHZhciBib3hBbmNob3IgPSBwMS5zdWIocDApLl91bml0KCkuX211bHQoc2VnbWVudEJveERpc3RhbmNlKS5fYWRkKHAwKTtcblxuICAgICAgICB2YXIgZGlzdGFuY2VUb0lubmVyRWRnZSA9IE1hdGgubWF4KE1hdGguYWJzKGJveERpc3RhbmNlVG9BbmNob3IgLSBmaXJzdEJveE9mZnNldCkgLSBzdGVwIC8gMiwgMCk7XG4gICAgICAgIHZhciBtYXhTY2FsZSA9IGxhYmVsTGVuZ3RoIC8gMiAvIGRpc3RhbmNlVG9Jbm5lckVkZ2U7XG5cbiAgICAgICAgYmJveGVzLnB1c2gobmV3IENvbGxpc2lvbkJveChib3hBbmNob3IsIC1ib3hTaXplIC8gMiwgLWJveFNpemUgLyAyLCBib3hTaXplIC8gMiwgYm94U2l6ZSAvIDIsIG1heFNjYWxlKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJib3hlcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByYnVzaCA9IHJlcXVpcmUoJ3JidXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sbGlzaW9uVGlsZTtcblxuZnVuY3Rpb24gQ29sbGlzaW9uVGlsZSh6b29tLCB0aWxlRXh0ZW50LCB0aWxlU2l6ZSkge1xuICAgIHRoaXMuem9vbSA9IHpvb207XG4gICAgdGhpcy50aWxlUGl4ZWxSYXRpbyA9IHRpbGVFeHRlbnQgLyB0aWxlU2l6ZTtcbn1cblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWluU2NhbGUgPSAwLjI1O1xuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUubWF4U2NhbGUgPSAyO1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uKGFuZ2xlLCBwaXRjaCkge1xuICAgIHRoaXMudHJlZSA9IHJidXNoKCk7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICAgIHRoaXMucm90YXRpb25NYXRyaXggPSBbY29zLCAtc2luLCBzaW4sIGNvc107XG5cbiAgICAvLyBTdHJldGNoIGJveGVzIGluIHkgZGlyZWN0aW9uIHRvIGFjY291bnQgZm9yIHRoZSBtYXAgdGlsdC5cbiAgICB0aGlzLnlTdHJldGNoID0gMSAvIE1hdGguY29zKHBpdGNoIC8gMTgwICogTWF0aC5QSSk7XG5cbiAgICAvLyBUaGUgYW1vdW50IHRoZSBtYXAgaXMgc3F1aXNoZWQgZGVwZW5kcyBvbiB0aGUgeSBwb3NpdGlvbi5cbiAgICAvLyBTb3J0IG9mIGFjY291bnQgZm9yIHRoaXMgYnkgbWFraW5nIGFsbCBib3hlcyBhIGJpdCBiaWdnZXIuXG4gICAgdGhpcy55U3RyZXRjaCA9IE1hdGgucG93KHRoaXMueVN0cmV0Y2gsIDEuMyk7XG59O1xuXG5Db2xsaXNpb25UaWxlLnByb3RvdHlwZS5wbGFjZUZlYXR1cmUgPSBmdW5jdGlvbihmZWF0dXJlKSB7XG5cbiAgICB2YXIgbWluUGxhY2VtZW50U2NhbGUgPSB0aGlzLm1pblNjYWxlO1xuICAgIHZhciByb3RhdGlvbk1hdHJpeCA9IHRoaXMucm90YXRpb25NYXRyaXg7XG4gICAgdmFyIHlTdHJldGNoID0gdGhpcy55U3RyZXRjaDtcblxuICAgIGZvciAodmFyIGIgPSAwOyBiIDwgZmVhdHVyZS5ib3hlcy5sZW5ndGg7IGIrKykge1xuXG4gICAgICAgIHZhciBib3ggPSBmZWF0dXJlLmJveGVzW2JdO1xuXG4gICAgICAgIHZhciBhbmNob3IgPSBib3guYW5jaG9yLm1hdE11bHQocm90YXRpb25NYXRyaXgpO1xuICAgICAgICB2YXIgeCA9IGFuY2hvci54O1xuICAgICAgICB2YXIgeSA9IGFuY2hvci55O1xuXG4gICAgICAgIGJveFswXSA9IHggKyBib3gueDE7XG4gICAgICAgIGJveFsxXSA9IHkgKyBib3gueTEgKiB5U3RyZXRjaDtcbiAgICAgICAgYm94WzJdID0geCArIGJveC54MjtcbiAgICAgICAgYm94WzNdID0geSArIGJveC55MiAqIHlTdHJldGNoO1xuXG4gICAgICAgIHZhciBibG9ja2luZ0JveGVzID0gdGhpcy50cmVlLnNlYXJjaChib3gpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tpbmdCb3hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJsb2NraW5nID0gYmxvY2tpbmdCb3hlc1tpXTtcbiAgICAgICAgICAgIHZhciBibG9ja2luZ0FuY2hvciA9IGJsb2NraW5nLmFuY2hvci5tYXRNdWx0KHJvdGF0aW9uTWF0cml4KTtcblxuICAgICAgICAgICAgLy8gRmluZCB0aGUgbG93ZXN0IHNjYWxlIGF0IHdoaWNoIHRoZSB0d28gYm94ZXMgY2FuIGZpdCBzaWRlIGJ5IHNpZGUgd2l0aG91dCBvdmVybGFwcGluZy5cbiAgICAgICAgICAgIC8vIE9yaWdpbmFsIGFsZ29yaXRobTpcbiAgICAgICAgICAgIHZhciBzMSA9IChibG9ja2luZy54MSAtIGJveC54MikgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSBsZWZ0IG9mIG9sZCBib3hcbiAgICAgICAgICAgIHZhciBzMiA9IChibG9ja2luZy54MiAtIGJveC54MSkgLyAoeCAtIGJsb2NraW5nQW5jaG9yLngpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSByaWdodCBvZiBvbGQgYm94XG4gICAgICAgICAgICB2YXIgczMgPSAoYmxvY2tpbmcueTEgLSBib3gueTIpICogeVN0cmV0Y2ggLyAoeSAtIGJsb2NraW5nQW5jaG9yLnkpOyAvLyBzY2FsZSBhdCB3aGljaCBuZXcgYm94IGlzIHRvIHRoZSB0b3Agb2Ygb2xkIGJveFxuICAgICAgICAgICAgdmFyIHM0ID0gKGJsb2NraW5nLnkyIC0gYm94LnkxKSAqIHlTdHJldGNoIC8gKHkgLSBibG9ja2luZ0FuY2hvci55KTsgLy8gc2NhbGUgYXQgd2hpY2ggbmV3IGJveCBpcyB0byB0aGUgYm90dG9tIG9mIG9sZCBib3hcblxuICAgICAgICAgICAgaWYgKGlzTmFOKHMxKSB8fCBpc05hTihzMikpIHMxID0gczIgPSAxO1xuICAgICAgICAgICAgaWYgKGlzTmFOKHMzKSB8fCBpc05hTihzNCkpIHMzID0gczQgPSAxO1xuXG4gICAgICAgICAgICB2YXIgY29sbGlzaW9uRnJlZVNjYWxlID0gTWF0aC5taW4oTWF0aC5tYXgoczEsIHMyKSwgTWF0aC5tYXgoczMsIHM0KSk7XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBibG9ja2luZy5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIEFmdGVyIGEgYm94J3MgbWF4U2NhbGUgdGhlIGxhYmVsIGhhcyBzaHJ1bmsgZW5vdWdoIHRoYXQgdGhlIGJveCBpcyBubyBsb25nZXIgbmVlZGVkIHRvIGNvdmVyIGl0LFxuICAgICAgICAgICAgICAgIC8vIHNvIHVuYmxvY2sgdGhlIG5ldyBib3ggYXQgdGhlIHNjYWxlIHRoYXQgdGhlIG9sZCBib3ggZGlzYXBwZWFycy5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBibG9ja2luZy5tYXhTY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbGxpc2lvbkZyZWVTY2FsZSA+IGJveC5tYXhTY2FsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBib3ggY2FuIG9ubHkgYmUgc2hvd24gYWZ0ZXIgaXQgaXMgdmlzaWJsZSwgdGhlbiB0aGUgYm94IGNhbiBuZXZlciBiZSBzaG93bi5cbiAgICAgICAgICAgICAgICAvLyBCdXQgdGhlIGxhYmVsIGNhbiBiZSBzaG93biBhZnRlciB0aGlzIGJveCBpcyBub3QgdmlzaWJsZS5cbiAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPSBib3gubWF4U2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb2xsaXNpb25GcmVlU2NhbGUgPiBtaW5QbGFjZW1lbnRTY2FsZSAmJlxuICAgICAgICAgICAgICAgICAgICBjb2xsaXNpb25GcmVlU2NhbGUgPj0gYmxvY2tpbmcucGxhY2VtZW50U2NhbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGNvbGxpc2lvbiBvY2N1cnMgYXQgYSBsb3dlciBzY2FsZSB0aGFuIHByZXZpb3VzbHkgZm91bmQgY29sbGlzaW9uc1xuICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgY29sbGlzaW9uIG9jY3VycyB3aGlsZSB0aGUgb3RoZXIgbGFiZWwgaXMgdmlzaWJsZVxuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB0aGlzIGlzIHRoZSBsb3dlc3Qgc2NhbGUgYXQgd2hpY2ggdGhlIGxhYmVsIHdvbid0IGNvbGxpZGUgd2l0aCBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIG1pblBsYWNlbWVudFNjYWxlID0gY29sbGlzaW9uRnJlZVNjYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPj0gdGhpcy5tYXhTY2FsZSkgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pblBsYWNlbWVudFNjYWxlO1xufTtcblxuQ29sbGlzaW9uVGlsZS5wcm90b3R5cGUuaW5zZXJ0RmVhdHVyZSA9IGZ1bmN0aW9uKGZlYXR1cmUsIG1pblBsYWNlbWVudFNjYWxlKSB7XG5cbiAgICB2YXIgYm94ZXMgPSBmZWF0dXJlLmJveGVzO1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYm94ZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgYm94ZXNba10ucGxhY2VtZW50U2NhbGUgPSBtaW5QbGFjZW1lbnRTY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobWluUGxhY2VtZW50U2NhbGUgPCB0aGlzLm1heFNjYWxlKSB7XG4gICAgICAgIHRoaXMudHJlZS5sb2FkKGJveGVzKTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW50ZXJwb2xhdGUgPSByZXF1aXJlKCcuLi91dGlsL2ludGVycG9sYXRlJyk7XG52YXIgQW5jaG9yID0gcmVxdWlyZSgnLi4vc3ltYm9sL2FuY2hvcicpO1xudmFyIGNoZWNrTWF4QW5nbGUgPSByZXF1aXJlKCcuL2NoZWNrX21heF9hbmdsZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEFuY2hvcnM7XG5cbmZ1bmN0aW9uIGdldEFuY2hvcnMobGluZSwgc3BhY2luZywgbWF4QW5nbGUsIHNoYXBlZFRleHQsIGdseXBoU2l6ZSwgYm94U2NhbGUsIG92ZXJzY2FsaW5nKSB7XG5cbiAgICAvLyBSZXNhbXBsZSBhIGxpbmUgdG8gZ2V0IGFuY2hvciBwb2ludHMgZm9yIGxhYmVscyBhbmQgY2hlY2sgdGhhdCBlYWNoXG4gICAgLy8gcG90ZW50aWFsIGxhYmVsIHBhc3NlcyB0ZXh0LW1heC1hbmdsZSBjaGVjayBhbmQgaGFzIGVub3VnaCBmcm9vbSB0byBmaXRcbiAgICAvLyBvbiB0aGUgbGluZS5cblxuICAgIHZhciBhbmdsZVdpbmRvd1NpemUgPSBzaGFwZWRUZXh0ID9cbiAgICAgICAgMyAvIDUgKiBnbHlwaFNpemUgKiBib3hTY2FsZSA6XG4gICAgICAgIDA7XG5cbiAgICAvLyBPZmZzZXQgdGhlIGZpcnN0IGFuY2hvciBieSBoYWxmIHRoZSBsYWJlbCBsZW5ndGggKG9yIGhhbGYgdGhlIHNwYWNpbmcgZGlzdGFuY2UgZm9yIGljb25zKS5cbiAgICAvLyBBZGQgYSBiaXQgb2YgZXh0cmEgb2Zmc2V0IHRvIGF2b2lkIGNvbGxpc2lvbnMgYXQgVCBpbnRlcnNlY3Rpb25zLlxuICAgIHZhciBsYWJlbExlbmd0aCA9IHNoYXBlZFRleHQgPyBzaGFwZWRUZXh0LnJpZ2h0IC0gc2hhcGVkVGV4dC5sZWZ0IDogc3BhY2luZztcbiAgICB2YXIgZXh0cmFPZmZzZXQgPSBnbHlwaFNpemUgKiAyO1xuICAgIHZhciBvZmZzZXQgPSAoKGxhYmVsTGVuZ3RoIC8gMiArIGV4dHJhT2Zmc2V0KSAqIGJveFNjYWxlICogb3ZlcnNjYWxpbmcpICUgc3BhY2luZztcblxuICAgIHJldHVybiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoICogYm94U2NhbGUsIGZhbHNlKTtcbn1cblxuXG5mdW5jdGlvbiByZXNhbXBsZShsaW5lLCBvZmZzZXQsIHNwYWNpbmcsIGFuZ2xlV2luZG93U2l6ZSwgbWF4QW5nbGUsIGxhYmVsTGVuZ3RoLCBwbGFjZUF0TWlkZGxlKSB7XG5cbiAgICB2YXIgZGlzdGFuY2UgPSAwLFxuICAgICAgICBtYXJrZWREaXN0YW5jZSA9IG9mZnNldCA/IG9mZnNldCAtIHNwYWNpbmcgOiAwO1xuXG4gICAgdmFyIGFuY2hvcnMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZS5sZW5ndGggLSAxOyBpKyspIHtcblxuICAgICAgICB2YXIgYSA9IGxpbmVbaV0sXG4gICAgICAgICAgICBiID0gbGluZVtpICsgMV07XG5cbiAgICAgICAgdmFyIHNlZ21lbnREaXN0ID0gYS5kaXN0KGIpLFxuICAgICAgICAgICAgYW5nbGUgPSBiLmFuZ2xlVG8oYSk7XG5cbiAgICAgICAgd2hpbGUgKG1hcmtlZERpc3RhbmNlICsgc3BhY2luZyA8IGRpc3RhbmNlICsgc2VnbWVudERpc3QpIHtcbiAgICAgICAgICAgIG1hcmtlZERpc3RhbmNlICs9IHNwYWNpbmc7XG5cbiAgICAgICAgICAgIHZhciB0ID0gKG1hcmtlZERpc3RhbmNlIC0gZGlzdGFuY2UpIC8gc2VnbWVudERpc3QsXG4gICAgICAgICAgICAgICAgeCA9IGludGVycG9sYXRlKGEueCwgYi54LCB0KSxcbiAgICAgICAgICAgICAgICB5ID0gaW50ZXJwb2xhdGUoYS55LCBiLnksIHQpO1xuXG4gICAgICAgICAgICBpZiAoeCA+PSAwICYmIHggPCA0MDk2ICYmIHkgPj0gMCAmJiB5IDwgNDA5Nikge1xuICAgICAgICAgICAgICAgIHggPSBNYXRoLnJvdW5kKHgpO1xuICAgICAgICAgICAgICAgIHkgPSBNYXRoLnJvdW5kKHkpO1xuICAgICAgICAgICAgICAgIHZhciBhbmNob3IgPSBuZXcgQW5jaG9yKHgsIHksIGFuZ2xlLCBpKTtcblxuICAgICAgICAgICAgICAgIGlmICghYW5nbGVXaW5kb3dTaXplIHx8IGNoZWNrTWF4QW5nbGUobGluZSwgYW5jaG9yLCBsYWJlbExlbmd0aCwgYW5nbGVXaW5kb3dTaXplLCBtYXhBbmdsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9ycy5wdXNoKGFuY2hvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGlzdGFuY2UgKz0gc2VnbWVudERpc3Q7XG4gICAgfVxuXG4gICAgaWYgKCFwbGFjZUF0TWlkZGxlICYmICFhbmNob3JzLmxlbmd0aCkge1xuICAgICAgICAvLyBUaGUgZmlyc3QgYXR0ZW1wdCBhdCBmaW5kaW5nIGFuY2hvcnMgYXQgd2hpY2ggbGFiZWxzIGNhbiBiZSBwbGFjZWQgZmFpbGVkLlxuICAgICAgICAvLyBUcnkgYWdhaW4sIGJ1dCB0aGlzIHRpbWUganVzdCB0cnkgcGxhY2luZyBvbmUgYW5jaG9yIGF0IHRoZSBtaWRkbGUgb2YgdGhlIGxpbmUuXG4gICAgICAgIC8vIFRoaXMgaGFzIHRoZSBtb3N0IGVmZmVjdCBmb3Igc2hvcnQgbGluZXMgaW4gb3ZlcnNjYWxlZCB0aWxlcywgc2luY2UgdGhlXG4gICAgICAgIC8vIGluaXRpYWwgb2Zmc2V0IHVzZWQgaW4gb3ZlcnNjYWxlZCB0aWxlcyBpcyBjYWxjdWxhdGVkIHRvIGFsaWduIGxhYmVscyB3aXRoIHBvc2l0aW9ucyBpblxuICAgICAgICAvLyBwYXJlbnQgdGlsZXMgaW5zdGVhZCBvZiBwbGFjaW5nIHRoZSBsYWJlbCBhcyBjbG9zZSB0byB0aGUgYmVnaW5uaW5nIGFzIHBvc3NpYmxlLlxuICAgICAgICBhbmNob3JzID0gcmVzYW1wbGUobGluZSwgZGlzdGFuY2UgLyAyLCBzcGFjaW5nLCBhbmdsZVdpbmRvd1NpemUsIG1heEFuZ2xlLCBsYWJlbExlbmd0aCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuY2hvcnM7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBCaW5QYWNrID0gcmVxdWlyZSgnLi9iaW5fcGFjaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoQXRsYXM7XG5mdW5jdGlvbiBHbHlwaEF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW5kZXggPSB7fTtcbiAgICB0aGlzLmlkcyA9IHt9O1xuICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbn1cblxuR2x5cGhBdGxhcy5wcm90b3R5cGUgPSB7XG4gICAgZ2V0IGRlYnVnKCkge1xuICAgICAgICByZXR1cm4gJ2NhbnZhcycgaW4gdGhpcztcbiAgICB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgJiYgIXRoaXMuY2FudmFzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuZ2V0R2x5cGhzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdseXBocyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghZ2x5cGhzW25hbWVdKSBnbHlwaHNbbmFtZV0gPSBbXTtcbiAgICAgICAgZ2x5cGhzW25hbWVdLnB1c2goaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBnbHlwaHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5nZXRSZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWN0cyA9IHt9LFxuICAgICAgICBzcGxpdCxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaWQ7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5pZHMpIHtcbiAgICAgICAgc3BsaXQgPSBrZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgbmFtZSA9IHNwbGl0WzBdO1xuICAgICAgICBpZCA9IHNwbGl0WzFdO1xuXG4gICAgICAgIGlmICghcmVjdHNbbmFtZV0pIHJlY3RzW25hbWVdID0ge307XG4gICAgICAgIHJlY3RzW25hbWVdW2lkXSA9IHRoaXMuaW5kZXhba2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVjdHM7XG59O1xuXG5HbHlwaEF0bGFzLnByb3RvdHlwZS5yZW1vdmVHbHlwaHMgPSBmdW5jdGlvbihpZCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmlkcykge1xuXG4gICAgICAgIHZhciBpZHMgPSB0aGlzLmlkc1trZXldO1xuXG4gICAgICAgIHZhciBwb3MgPSBpZHMuaW5kZXhPZihpZCk7XG4gICAgICAgIGlmIChwb3MgPj0gMCkgaWRzLnNwbGljZShwb3MsIDEpO1xuICAgICAgICB0aGlzLmlkc1trZXldID0gaWRzO1xuXG4gICAgICAgIGlmICghaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHJlY3QgPSB0aGlzLmluZGV4W2tleV07XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHJlY3QuaDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5KSArIHJlY3QueDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHJlY3QudzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuXG4gICAgICAgICAgICB0aGlzLmJpbi5yZWxlYXNlKHJlY3QpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pbmRleFtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWRzW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHRoaXMudXBkYXRlVGV4dHVyZSh0aGlzLmdsKTtcbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLmFkZEdseXBoID0gZnVuY3Rpb24oaWQsIG5hbWUsIGdseXBoLCBidWZmZXIpIHtcbiAgICBpZiAoIWdseXBoKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybignbWlzc2luZyBnbHlwaCcsIGNvZGUsIFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIGtleSA9IG5hbWUgKyBcIiNcIiArIGdseXBoLmlkO1xuXG4gICAgLy8gVGhlIGdseXBoIGlzIGFscmVhZHkgaW4gdGhpcyB0ZXh0dXJlLlxuICAgIGlmICh0aGlzLmluZGV4W2tleV0pIHtcbiAgICAgICAgaWYgKHRoaXMuaWRzW2tleV0uaW5kZXhPZihpZCkgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmlkc1trZXldLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZGV4W2tleV07XG4gICAgfVxuXG4gICAgLy8gVGhlIGdseXBoIGJpdG1hcCBoYXMgemVybyB3aWR0aC5cbiAgICBpZiAoIWdseXBoLmJpdG1hcCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYnVmZmVyZWRXaWR0aCA9IGdseXBoLndpZHRoICsgYnVmZmVyICogMjtcbiAgICB2YXIgYnVmZmVyZWRIZWlnaHQgPSBnbHlwaC5oZWlnaHQgKyBidWZmZXIgKiAyO1xuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuICAgIHZhciBwYWNrV2lkdGggPSBidWZmZXJlZFdpZHRoICsgMiAqIHBhZGRpbmc7XG4gICAgdmFyIHBhY2tIZWlnaHQgPSBidWZmZXJlZEhlaWdodCArIDIgKiBwYWRkaW5nO1xuXG4gICAgLy8gSW5jcmVhc2UgdG8gbmV4dCBudW1iZXIgZGl2aXNpYmxlIGJ5IDQsIGJ1dCBhdCBsZWFzdCAxLlxuICAgIC8vIFRoaXMgaXMgc28gd2UgY2FuIHNjYWxlIGRvd24gdGhlIHRleHR1cmUgY29vcmRpbmF0ZXMgYW5kIHBhY2sgdGhlbVxuICAgIC8vIGludG8gMiBieXRlcyByYXRoZXIgdGhhbiA0IGJ5dGVzLlxuICAgIHBhY2tXaWR0aCArPSAoNCAtIHBhY2tXaWR0aCAlIDQpO1xuICAgIHBhY2tIZWlnaHQgKz0gKDQgLSBwYWNrSGVpZ2h0ICUgNCk7XG5cbiAgICB2YXIgcmVjdCA9IHRoaXMuYmluLmFsbG9jYXRlKHBhY2tXaWR0aCwgcGFja0hlaWdodCk7XG4gICAgaWYgKHJlY3QueCA8IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdnbHlwaCBiaXRtYXAgb3ZlcmZsb3cnKTtcbiAgICAgICAgcmV0dXJuIHsgZ2x5cGg6IGdseXBoLCByZWN0OiBudWxsIH07XG4gICAgfVxuXG4gICAgdGhpcy5pbmRleFtrZXldID0gcmVjdDtcbiAgICB0aGlzLmlkc1trZXldID0gW2lkXTtcblxuICAgIHZhciB0YXJnZXQgPSB0aGlzLmRhdGE7XG4gICAgdmFyIHNvdXJjZSA9IGdseXBoLmJpdG1hcDtcbiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGJ1ZmZlcmVkSGVpZ2h0OyB5KyspIHtcbiAgICAgICAgdmFyIHkxID0gdGhpcy53aWR0aCAqIChyZWN0LnkgKyB5ICsgcGFkZGluZykgKyByZWN0LnggKyBwYWRkaW5nO1xuICAgICAgICB2YXIgeTIgPSBidWZmZXJlZFdpZHRoICogeTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBidWZmZXJlZFdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgIHRhcmdldFt5MSArIHhdID0gc291cmNlW3kyICsgeF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcblxuICAgIHJldHVybiByZWN0O1xufTtcblxuR2x5cGhBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsKSB7XG4gICAgdGhpcy5nbCA9IGdsO1xuICAgIGlmICghdGhpcy50ZXh0dXJlKSB7XG4gICAgICAgIHRoaXMudGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy50ZXh0dXJlKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuQUxQSEEsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCAwLCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLnRleHR1cmUpO1xuICAgIH1cbn07XG5cbkdseXBoQXRsYXMucHJvdG90eXBlLnVwZGF0ZVRleHR1cmUgPSBmdW5jdGlvbihnbCkge1xuICAgIHRoaXMuYmluZChnbCk7XG4gICAgaWYgKHRoaXMuZGlydHkpIHtcblxuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCBnbC5BTFBIQSwgZ2wuVU5TSUdORURfQllURSwgdGhpcy5kYXRhKTtcblxuICAgICAgICAvLyBERUJVR1xuICAgICAgICBpZiAodGhpcy5jdHgpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gdGhpcy5jdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKywgaiArPSA0KSB7XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2pdID0gdGhpcy5kYXRhW2ldO1xuICAgICAgICAgICAgICAgIGRhdGEuZGF0YVtqICsgMV0gPSB0aGlzLmRhdGFbaV07XG4gICAgICAgICAgICAgICAgZGF0YS5kYXRhW2ogKyAyXSA9IHRoaXMuZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBkYXRhLmRhdGFbaiArIDNdID0gMjU1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54LCBmcmVlLnksIGZyZWUudywgZnJlZS5oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcblxuICAgICAgICB0aGlzLmRpcnR5ID0gZmFsc2U7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGl6ZVVSTCA9IHJlcXVpcmUoJy4uL3V0aWwvbWFwYm94Jykubm9ybWFsaXplR2x5cGhzVVJMO1xudmFyIGdldEFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbC9hamF4JykuZ2V0QXJyYXlCdWZmZXI7XG52YXIgR2x5cGhzID0gcmVxdWlyZSgnLi4vdXRpbC9nbHlwaHMnKTtcbnZhciBQcm90b2J1ZiA9IHJlcXVpcmUoJ3BiZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdseXBoU291cmNlO1xuXG4vKipcbiAqIEEgZ2x5cGggc291cmNlIGhhcyBhIFVSTCBmcm9tIHdoaWNoIHRvIGxvYWQgbmV3IGdseXBocyBhbmQgb3ducyBhIEdseXBoQXRsYXNcbiAqIHRoYXQgc3RvcmVzIGN1cnJlbnRseS1sb2FkZWQgZ2x5cGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgZ2x5cGggdGVtcGxhdGUgdXJsXG4gKiBAcGFyYW0ge09iamVjdH0gZ2x5cGhBdGxhcyBnbHlwaCBhdGxhcyBvYmplY3RcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEdseXBoU291cmNlKHVybCwgZ2x5cGhBdGxhcykge1xuICAgIHRoaXMudXJsID0gdXJsICYmIG5vcm1hbGl6ZVVSTCh1cmwpO1xuICAgIHRoaXMuZ2x5cGhBdGxhcyA9IGdseXBoQXRsYXM7XG4gICAgdGhpcy5zdGFja3MgPSBbXTtcbiAgICB0aGlzLmxvYWRpbmcgPSB7fTtcbn1cblxuR2x5cGhTb3VyY2UucHJvdG90eXBlLmdldFNpbXBsZUdseXBocyA9IGZ1bmN0aW9uKGZvbnRzdGFjaywgZ2x5cGhJRHMsIHVpZCwgY2FsbGJhY2spIHtcblxuICAgIGlmICh0aGlzLnN0YWNrc1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMuc3RhY2tzW2ZvbnRzdGFja10gPSB7fTtcblxuICAgIHZhciBnbHlwaHMgPSB7fTtcblxuICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja107XG4gICAgdmFyIGdseXBoQXRsYXMgPSB0aGlzLmdseXBoQXRsYXM7XG5cbiAgICAvLyB0aGUgbnVtYmVyIG9mIHBpeGVscyB0aGUgc2RmIGJpdG1hcHMgYXJlIHBhZGRlZCBieVxuICAgIHZhciBidWZmZXIgPSAzO1xuXG4gICAgdmFyIG1pc3NpbmcgPSB7fTtcbiAgICB2YXIgcmVtYWluaW5nID0gMDtcbiAgICB2YXIgcmFuZ2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdseXBoSURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnbHlwaElEID0gZ2x5cGhJRHNbaV07XG4gICAgICAgIHJhbmdlID0gTWF0aC5mbG9vcihnbHlwaElEIC8gMjU2KTtcblxuICAgICAgICBpZiAoc3RhY2tbcmFuZ2VdKSB7XG4gICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFja1tyYW5nZV0uZ2x5cGhzW2dseXBoSURdO1xuICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICBpZiAoZ2x5cGgpIGdseXBoc1tnbHlwaElEXSA9IG5ldyBTaW1wbGVHbHlwaChnbHlwaCwgcmVjdCwgYnVmZmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nW3JhbmdlXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1tyYW5nZV0gPSBbXTtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pc3NpbmdbcmFuZ2VdLnB1c2goZ2x5cGhJRCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXJlbWFpbmluZykgY2FsbGJhY2sodW5kZWZpbmVkLCBnbHlwaHMpO1xuXG4gICAgdmFyIG9uUmFuZ2VMb2FkZWQgPSBmdW5jdGlvbihlcnIsIHJhbmdlLCBkYXRhKSB7XG4gICAgICAgIC8vIFRPRE8gbm90IGJlIHNpbGVudCBhYm91dCBlcnJvcnNcbiAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2tzW2ZvbnRzdGFja11bcmFuZ2VdID0gZGF0YS5zdGFja3NbMF07XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1pc3NpbmdbcmFuZ2VdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdseXBoSUQgPSBtaXNzaW5nW3JhbmdlXVtpXTtcbiAgICAgICAgICAgICAgICB2YXIgZ2x5cGggPSBzdGFjay5nbHlwaHNbZ2x5cGhJRF07XG4gICAgICAgICAgICAgICAgdmFyIHJlY3QgID0gZ2x5cGhBdGxhcy5hZGRHbHlwaCh1aWQsIGZvbnRzdGFjaywgZ2x5cGgsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKGdseXBoKSBnbHlwaHNbZ2x5cGhJRF0gPSBuZXcgU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVtYWluaW5nLS07XG4gICAgICAgIGlmICghcmVtYWluaW5nKSBjYWxsYmFjayh1bmRlZmluZWQsIGdseXBocyk7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgZm9yICh2YXIgciBpbiBtaXNzaW5nKSB7XG4gICAgICAgIHRoaXMubG9hZFJhbmdlKGZvbnRzdGFjaywgciwgb25SYW5nZUxvYWRlZCk7XG4gICAgfVxufTtcblxuLy8gQSBzaW1wbGlmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnbHlwaCBjb250YWluaW5nIG9ubHkgdGhlIHByb3BlcnRpZXMgbmVlZGVkIGZvciBzaGFwaW5nLlxuZnVuY3Rpb24gU2ltcGxlR2x5cGgoZ2x5cGgsIHJlY3QsIGJ1ZmZlcikge1xuICAgIHZhciBwYWRkaW5nID0gMTtcbiAgICB0aGlzLmFkdmFuY2UgPSBnbHlwaC5hZHZhbmNlO1xuICAgIHRoaXMubGVmdCA9IGdseXBoLmxlZnQgLSBidWZmZXIgLSBwYWRkaW5nO1xuICAgIHRoaXMudG9wID0gZ2x5cGgudG9wICsgYnVmZmVyICsgcGFkZGluZztcbiAgICB0aGlzLnJlY3QgPSByZWN0O1xufVxuXG5HbHlwaFNvdXJjZS5wcm90b3R5cGUubG9hZFJhbmdlID0gZnVuY3Rpb24oZm9udHN0YWNrLCByYW5nZSwgY2FsbGJhY2spIHtcblxuICAgIGlmIChyYW5nZSAqIDI1NiA+IDY1NTM1KSByZXR1cm4gY2FsbGJhY2soJ2d5cGhzID4gNjU1MzUgbm90IHN1cHBvcnRlZCcpO1xuXG4gICAgaWYgKHRoaXMubG9hZGluZ1tmb250c3RhY2tdID09PSB1bmRlZmluZWQpIHRoaXMubG9hZGluZ1tmb250c3RhY2tdID0ge307XG4gICAgdmFyIGxvYWRpbmcgPSB0aGlzLmxvYWRpbmdbZm9udHN0YWNrXTtcblxuICAgIGlmIChsb2FkaW5nW3JhbmdlXSkge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXS5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2FkaW5nW3JhbmdlXSA9IFtjYWxsYmFja107XG5cbiAgICAgICAgdmFyIHJhbmdlTmFtZSA9IChyYW5nZSAqIDI1NikgKyAnLScgKyAocmFuZ2UgKiAyNTYgKyAyNTUpO1xuICAgICAgICB2YXIgdXJsID0gZ2x5cGhVcmwoZm9udHN0YWNrLCByYW5nZU5hbWUsIHRoaXMudXJsKTtcblxuICAgICAgICBnZXRBcnJheUJ1ZmZlcih1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgdmFyIGdseXBocyA9ICFlcnIgJiYgbmV3IEdseXBocyhuZXcgUHJvdG9idWYobmV3IFVpbnQ4QXJyYXkoZGF0YSkpKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1tyYW5nZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2FkaW5nW3JhbmdlXVtpXShlcnIsIHJhbmdlLCBnbHlwaHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGxvYWRpbmdbcmFuZ2VdO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFVzZSBDTkFNRSBzaGFyZGluZyB0byBsb2FkIGEgc3BlY2lmaWMgZ2x5cGggcmFuZ2Ugb3ZlciBhIHJhbmRvbWl6ZWRcbiAqIGJ1dCBjb25zaXN0ZW50IHN1YmRvbWFpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250c3RhY2sgY29tbWEtam9pbmVkIGZvbnRzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmFuZ2UgY29tbWEtam9pbmVkIHJhbmdlXG4gKiBAcGFyYW0ge3VybH0gdXJsIHRlbXBsYXRlZCB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3ViZG9tYWlucz1hYmNdIHN1YmRvbWFpbnMgYXMgYSBzdHJpbmcgd2hlcmUgZWFjaCBsZXR0ZXIgaXMgb25lLlxuICogQHJldHVybnMge3N0cmluZ30gYSB1cmwgdG8gbG9hZCB0aGF0IHNlY3Rpb24gb2YgZ2x5cGhzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBnbHlwaFVybChmb250c3RhY2ssIHJhbmdlLCB1cmwsIHN1YmRvbWFpbnMpIHtcbiAgICBzdWJkb21haW5zID0gc3ViZG9tYWlucyB8fCAnYWJjJztcblxuICAgIHJldHVybiB1cmxcbiAgICAgICAgLnJlcGxhY2UoJ3tzfScsIHN1YmRvbWFpbnNbZm9udHN0YWNrLmxlbmd0aCAlIHN1YmRvbWFpbnMubGVuZ3RoXSlcbiAgICAgICAgLnJlcGxhY2UoJ3tmb250c3RhY2t9JywgZm9udHN0YWNrKVxuICAgICAgICAucmVwbGFjZSgne3JhbmdlfScsIHJhbmdlKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmVhdHVyZXMsIHRleHRGZWF0dXJlcywgZ2VvbWV0cmllcykge1xuXG4gICAgdmFyIGxlZnRJbmRleCA9IHt9LFxuICAgICAgICByaWdodEluZGV4ID0ge30sXG4gICAgICAgIG1lcmdlZEZlYXR1cmVzID0gW10sXG4gICAgICAgIG1lcmdlZEdlb20gPSBbXSxcbiAgICAgICAgbWVyZ2VkVGV4dHMgPSBbXSxcbiAgICAgICAgbWVyZ2VkSW5kZXggPSAwLFxuICAgICAgICBrO1xuXG4gICAgZnVuY3Rpb24gYWRkKGspIHtcbiAgICAgICAgbWVyZ2VkRmVhdHVyZXMucHVzaChmZWF0dXJlc1trXSk7XG4gICAgICAgIG1lcmdlZEdlb20ucHVzaChnZW9tZXRyaWVzW2tdKTtcbiAgICAgICAgbWVyZ2VkVGV4dHMucHVzaCh0ZXh0RmVhdHVyZXNba10pO1xuICAgICAgICBtZXJnZWRJbmRleCsrO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKSB7XG4gICAgICAgIHZhciBpID0gcmlnaHRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgZGVsZXRlIHJpZ2h0SW5kZXhbbGVmdEtleV07XG4gICAgICAgIHJpZ2h0SW5kZXhbcmlnaHRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnBvcCgpO1xuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdID0gbWVyZ2VkR2VvbVtpXVswXS5jb25jYXQoZ2VvbVswXSk7XG4gICAgICAgIHJldHVybiBpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlRnJvbUxlZnQobGVmdEtleSwgcmlnaHRLZXksIGdlb20pIHtcbiAgICAgICAgdmFyIGkgPSBsZWZ0SW5kZXhbcmlnaHRLZXldO1xuICAgICAgICBkZWxldGUgbGVmdEluZGV4W3JpZ2h0S2V5XTtcbiAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gaTtcblxuICAgICAgICBtZXJnZWRHZW9tW2ldWzBdLnNoaWZ0KCk7XG4gICAgICAgIG1lcmdlZEdlb21baV1bMF0gPSBnZW9tWzBdLmNvbmNhdChtZXJnZWRHZW9tW2ldWzBdKTtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0S2V5KHRleHQsIGdlb20sIG9uUmlnaHQpIHtcbiAgICAgICAgdmFyIHBvaW50ID0gb25SaWdodCA/IGdlb21bMF1bZ2VvbVswXS5sZW5ndGggLSAxXSA6IGdlb21bMF1bMF07XG4gICAgICAgIHJldHVybiB0ZXh0ICsgJzonICsgcG9pbnQueCArICc6JyArIHBvaW50Lnk7XG4gICAgfVxuXG4gICAgZm9yIChrID0gMDsgayA8IGZlYXR1cmVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBnZW9tID0gZ2VvbWV0cmllc1trXSxcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0RmVhdHVyZXNba107XG5cbiAgICAgICAgaWYgKCF0ZXh0KSB7XG4gICAgICAgICAgICBhZGQoayk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsZWZ0S2V5ID0gZ2V0S2V5KHRleHQsIGdlb20pLFxuICAgICAgICAgICAgcmlnaHRLZXkgPSBnZXRLZXkodGV4dCwgZ2VvbSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKChsZWZ0S2V5IGluIHJpZ2h0SW5kZXgpICYmIChyaWdodEtleSBpbiBsZWZ0SW5kZXgpICYmIChyaWdodEluZGV4W2xlZnRLZXldICE9PSBsZWZ0SW5kZXhbcmlnaHRLZXldKSkge1xuICAgICAgICAgICAgLy8gZm91bmQgbGluZXMgd2l0aCB0aGUgc2FtZSB0ZXh0IGFkamFjZW50IHRvIGJvdGggZW5kcyBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZSBhbGwgdGhyZWVcbiAgICAgICAgICAgIHZhciBqID0gbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG4gICAgICAgICAgICB2YXIgaSA9IG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBtZXJnZWRHZW9tW2pdKTtcblxuICAgICAgICAgICAgZGVsZXRlIGxlZnRJbmRleFtsZWZ0S2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSByaWdodEluZGV4W3JpZ2h0S2V5XTtcblxuICAgICAgICAgICAgcmlnaHRJbmRleFtnZXRLZXkodGV4dCwgbWVyZ2VkR2VvbVtpXSwgdHJ1ZSldID0gaTtcbiAgICAgICAgICAgIG1lcmdlZEdlb21bal0gPSBudWxsO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobGVmdEtleSBpbiByaWdodEluZGV4KSB7XG4gICAgICAgICAgICAvLyBmb3VuZCBtZXJnZWFibGUgbGluZSBhZGphY2VudCB0byB0aGUgc3RhcnQgb2YgdGhlIGN1cnJlbnQgbGluZSwgbWVyZ2VcbiAgICAgICAgICAgIG1lcmdlRnJvbVJpZ2h0KGxlZnRLZXksIHJpZ2h0S2V5LCBnZW9tKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHJpZ2h0S2V5IGluIGxlZnRJbmRleCkge1xuICAgICAgICAgICAgLy8gZm91bmQgbWVyZ2VhYmxlIGxpbmUgYWRqYWNlbnQgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudCBsaW5lLCBtZXJnZVxuICAgICAgICAgICAgbWVyZ2VGcm9tTGVmdChsZWZ0S2V5LCByaWdodEtleSwgZ2VvbSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vIGFkamFjZW50IGxpbmVzLCBhZGQgYXMgYSBuZXcgaXRlbVxuICAgICAgICAgICAgYWRkKGspO1xuICAgICAgICAgICAgbGVmdEluZGV4W2xlZnRLZXldID0gbWVyZ2VkSW5kZXggLSAxO1xuICAgICAgICAgICAgcmlnaHRJbmRleFtyaWdodEtleV0gPSBtZXJnZWRJbmRleCAtIDE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmZWF0dXJlczogbWVyZ2VkRmVhdHVyZXMsXG4gICAgICAgIHRleHRGZWF0dXJlczogbWVyZ2VkVGV4dHMsXG4gICAgICAgIGdlb21ldHJpZXM6IG1lcmdlZEdlb21cbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcbnZhciBBbmNob3IgPSByZXF1aXJlKCcuLi9zeW1ib2wvYW5jaG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEljb25RdWFkczogZ2V0SWNvblF1YWRzLFxuICAgIGdldEdseXBoUXVhZHM6IGdldEdseXBoUXVhZHNcbn07XG5cbnZhciBtaW5TY2FsZSA9IDAuNTsgLy8gdW5kZXJzY2FsZSBieSAxIHpvb20gbGV2ZWxcblxuZnVuY3Rpb24gU3ltYm9sUXVhZChhbmNob3IsIHRsLCB0ciwgYmwsIGJyLCB0ZXgsIGFuZ2xlLCBtaW5TY2FsZSwgbWF4U2NhbGUpIHtcbiAgICB0aGlzLmFuY2hvciA9IGFuY2hvcjtcbiAgICB0aGlzLnRsID0gdGw7XG4gICAgdGhpcy50ciA9IHRyO1xuICAgIHRoaXMuYmwgPSBibDtcbiAgICB0aGlzLmJyID0gYnI7XG4gICAgdGhpcy50ZXggPSB0ZXg7XG4gICAgdGhpcy5hbmdsZSA9IGFuZ2xlO1xuICAgIHRoaXMubWluU2NhbGUgPSBtaW5TY2FsZTtcbiAgICB0aGlzLm1heFNjYWxlID0gbWF4U2NhbGU7XG59XG5cbmZ1bmN0aW9uIGdldEljb25RdWFkcyhhbmNob3IsIHNoYXBlZEljb24sIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHJlY3QgPSBzaGFwZWRJY29uLmltYWdlLnJlY3Q7XG5cbiAgICB2YXIgYm9yZGVyID0gMTtcbiAgICB2YXIgbGVmdCA9IHNoYXBlZEljb24ubGVmdCAtIGJvcmRlcjtcbiAgICB2YXIgcmlnaHQgPSBsZWZ0ICsgcmVjdC53O1xuICAgIHZhciB0b3AgPSBzaGFwZWRJY29uLnRvcCAtIGJvcmRlcjtcbiAgICB2YXIgYm90dG9tID0gdG9wICsgcmVjdC5oO1xuICAgIHZhciB0bCA9IG5ldyBQb2ludChsZWZ0LCB0b3ApO1xuICAgIHZhciB0ciA9IG5ldyBQb2ludChyaWdodCwgdG9wKTtcbiAgICB2YXIgYnIgPSBuZXcgUG9pbnQocmlnaHQsIGJvdHRvbSk7XG4gICAgdmFyIGJsID0gbmV3IFBvaW50KGxlZnQsIGJvdHRvbSk7XG5cbiAgICB2YXIgYW5nbGUgPSBsYXlvdXRbJ2ljb24tcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIGlmIChhbG9uZ0xpbmUpIHtcbiAgICAgICAgdmFyIHByZXYgPSBsaW5lW2FuY2hvci5zZWdtZW50XTtcbiAgICAgICAgYW5nbGUgKz0gTWF0aC5hdGFuMihhbmNob3IueSAtIHByZXYueSwgYW5jaG9yLnggLSBwcmV2LngpO1xuICAgIH1cblxuICAgIGlmIChhbmdsZSkge1xuICAgICAgICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpLFxuICAgICAgICAgICAgY29zID0gTWF0aC5jb3MoYW5nbGUpLFxuICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgIHRsID0gdGwubWF0TXVsdChtYXRyaXgpO1xuICAgICAgICB0ciA9IHRyLm1hdE11bHQobWF0cml4KTtcbiAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgIGJyID0gYnIubWF0TXVsdChtYXRyaXgpO1xuICAgIH1cblxuICAgIHJldHVybiBbbmV3IFN5bWJvbFF1YWQoYW5jaG9yLCB0bCwgdHIsIGJsLCBiciwgc2hhcGVkSWNvbi5pbWFnZS5yZWN0LCAwLCBtaW5TY2FsZSwgSW5maW5pdHkpXTtcbn1cblxuZnVuY3Rpb24gZ2V0R2x5cGhRdWFkcyhhbmNob3IsIHNoYXBpbmcsIGJveFNjYWxlLCBsaW5lLCBsYXlvdXQsIGFsb25nTGluZSkge1xuXG4gICAgdmFyIHRleHRSb3RhdGUgPSBsYXlvdXRbJ3RleHQtcm90YXRlJ10gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBrZWVwVXByaWdodCA9IGxheW91dFsndGV4dC1rZWVwLXVwcmlnaHQnXTtcblxuICAgIHZhciBwb3NpdGlvbmVkR2x5cGhzID0gc2hhcGluZy5wb3NpdGlvbmVkR2x5cGhzO1xuICAgIHZhciBxdWFkcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2tdO1xuICAgICAgICB2YXIgZ2x5cGggPSBwb3NpdGlvbmVkR2x5cGguZ2x5cGg7XG4gICAgICAgIHZhciByZWN0ID0gZ2x5cGgucmVjdDtcblxuICAgICAgICBpZiAoIXJlY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjZW50ZXJYID0gKHBvc2l0aW9uZWRHbHlwaC54ICsgZ2x5cGguYWR2YW5jZSAvIDIpICogYm94U2NhbGU7XG5cbiAgICAgICAgdmFyIGdseXBoSW5zdGFuY2VzO1xuICAgICAgICB2YXIgbGFiZWxNaW5TY2FsZSA9IG1pblNjYWxlO1xuICAgICAgICBpZiAoYWxvbmdMaW5lKSB7XG4gICAgICAgICAgICBnbHlwaEluc3RhbmNlcyA9IFtdO1xuICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIDEpO1xuICAgICAgICAgICAgaWYgKGtlZXBVcHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgbGFiZWxNaW5TY2FsZSA9IE1hdGgubWluKGxhYmVsTWluU2NhbGUsIGdldFNlZ21lbnRHbHlwaHMoZ2x5cGhJbnN0YW5jZXMsIGFuY2hvciwgY2VudGVyWCwgbGluZSwgYW5jaG9yLnNlZ21lbnQsIC0xKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdseXBoSW5zdGFuY2VzID0gW3tcbiAgICAgICAgICAgICAgICBhbmNob3I6IGFuY2hvcixcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICAgICAgYW5nbGU6IDAsXG4gICAgICAgICAgICAgICAgbWF4U2NhbGU6IEluZmluaXR5LFxuICAgICAgICAgICAgICAgIG1pblNjYWxlOiBtaW5TY2FsZVxuICAgICAgICAgICAgfV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeDEgPSBwb3NpdGlvbmVkR2x5cGgueCArIGdseXBoLmxlZnQsXG4gICAgICAgICAgICB5MSA9IHBvc2l0aW9uZWRHbHlwaC55IC0gZ2x5cGgudG9wLFxuICAgICAgICAgICAgeDIgPSB4MSArIHJlY3QudyxcbiAgICAgICAgICAgIHkyID0geTEgKyByZWN0LmgsXG5cbiAgICAgICAgICAgIG90bCA9IG5ldyBQb2ludCh4MSwgeTEpLFxuICAgICAgICAgICAgb3RyID0gbmV3IFBvaW50KHgyLCB5MSksXG4gICAgICAgICAgICBvYmwgPSBuZXcgUG9pbnQoeDEsIHkyKSxcbiAgICAgICAgICAgIG9iciA9IG5ldyBQb2ludCh4MiwgeTIpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2x5cGhJbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gZ2x5cGhJbnN0YW5jZXNbaV0sXG4gICAgICAgICAgICAgICAgdGwgPSBvdGwsXG4gICAgICAgICAgICAgICAgdHIgPSBvdHIsXG4gICAgICAgICAgICAgICAgYmwgPSBvYmwsXG4gICAgICAgICAgICAgICAgYnIgPSBvYnIsXG4gICAgICAgICAgICAgICAgYW5nbGUgPSBpbnN0YW5jZS5hbmdsZSArIHRleHRSb3RhdGU7XG5cbiAgICAgICAgICAgIGlmIChhbmdsZSkge1xuICAgICAgICAgICAgICAgIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4ID0gW2NvcywgLXNpbiwgc2luLCBjb3NdO1xuXG4gICAgICAgICAgICAgICAgdGwgPSB0bC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgdHIgPSB0ci5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYmwgPSBibC5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgYnIgPSBici5tYXRNdWx0KG1hdHJpeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgbGFiZWwgZnJvbSBleHRlbmRpbmcgcGFzdCB0aGUgZW5kIG9mIHRoZSBsaW5lXG4gICAgICAgICAgICB2YXIgZ2x5cGhNaW5TY2FsZSA9IE1hdGgubWF4KGluc3RhbmNlLm1pblNjYWxlLCBsYWJlbE1pblNjYWxlKTtcblxuICAgICAgICAgICAgdmFyIGdseXBoQW5nbGUgPSAoYW5jaG9yLmFuZ2xlICsgdGV4dFJvdGF0ZSArIGluc3RhbmNlLm9mZnNldCArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSk7XG4gICAgICAgICAgICBxdWFkcy5wdXNoKG5ldyBTeW1ib2xRdWFkKGluc3RhbmNlLmFuY2hvciwgdGwsIHRyLCBibCwgYnIsIHJlY3QsIGdseXBoQW5nbGUsIGdseXBoTWluU2NhbGUsIGluc3RhbmNlLm1heFNjYWxlKSk7XG5cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBxdWFkcztcbn1cblxuZnVuY3Rpb24gZ2V0U2VnbWVudEdseXBocyhnbHlwaHMsIGFuY2hvciwgb2Zmc2V0LCBsaW5lLCBzZWdtZW50LCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgdXBzaWRlRG93biA9IGRpcmVjdGlvbiA8IDA7XG5cbiAgICBpZiAob2Zmc2V0IDwgMCkgZGlyZWN0aW9uICo9IC0xO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHNlZ21lbnQrKztcblxuICAgIHZhciBuZXdBbmNob3IgPSBhbmNob3I7XG4gICAgdmFyIGVuZCA9IGxpbmVbc2VnbWVudF07XG4gICAgdmFyIHByZXZTY2FsZSA9IEluZmluaXR5O1xuXG4gICAgb2Zmc2V0ID0gTWF0aC5hYnMob2Zmc2V0KTtcblxuICAgIHZhciBwbGFjZW1lbnRTY2FsZSA9IG1pblNjYWxlO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgdmFyIGRpc3RhbmNlID0gbmV3QW5jaG9yLmRpc3QoZW5kKTtcbiAgICAgICAgdmFyIHNjYWxlID0gb2Zmc2V0IC8gZGlzdGFuY2U7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBhbmdsZSBvZiB0aGUgbGluZSBzZWdtZW50XG4gICAgICAgIHZhciBhbmdsZSA9IE1hdGguYXRhbjIoZW5kLnkgLSBuZXdBbmNob3IueSwgZW5kLnggLSBuZXdBbmNob3IueCk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPCAwKSBhbmdsZSArPSBNYXRoLlBJO1xuICAgICAgICBpZiAodXBzaWRlRG93bikgYW5nbGUgKz0gTWF0aC5QSTtcblxuICAgICAgICBnbHlwaHMucHVzaCh7XG4gICAgICAgICAgICBhbmNob3I6IG5ldyBBbmNob3IobmV3QW5jaG9yLngsIG5ld0FuY2hvci55LCBhbmNob3IuYW5nbGUpLFxuICAgICAgICAgICAgb2Zmc2V0OiB1cHNpZGVEb3duID8gTWF0aC5QSSA6IDAsXG4gICAgICAgICAgICBtaW5TY2FsZTogc2NhbGUsXG4gICAgICAgICAgICBtYXhTY2FsZTogcHJldlNjYWxlLFxuICAgICAgICAgICAgYW5nbGU6IChhbmdsZSArIDIgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHNjYWxlIDw9IHBsYWNlbWVudFNjYWxlKSBicmVhaztcblxuICAgICAgICBuZXdBbmNob3IgPSBlbmQ7XG5cbiAgICAgICAgLy8gc2tpcCBkdXBsaWNhdGUgbm9kZXNcbiAgICAgICAgd2hpbGUgKG5ld0FuY2hvci5lcXVhbHMoZW5kKSkge1xuICAgICAgICAgICAgc2VnbWVudCArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICBlbmQgPSBsaW5lW3NlZ21lbnRdO1xuICAgICAgICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdW5pdCA9IGVuZC5zdWIobmV3QW5jaG9yKS5fdW5pdCgpO1xuICAgICAgICBuZXdBbmNob3IgPSBuZXdBbmNob3Iuc3ViKHVuaXQuX211bHQoZGlzdGFuY2UpKTtcblxuICAgICAgICBwcmV2U2NhbGUgPSBzY2FsZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2VtZW50U2NhbGU7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXNvbHZlVG9rZW5zID0gcmVxdWlyZSgnLi4vdXRpbC90b2tlbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVJY29ucztcblxuLy8gRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGljb25zIG5lZWQgdG8gYmUgbG9hZGVkLlxuZnVuY3Rpb24gcmVzb2x2ZUljb25zKGZlYXR1cmVzLCBsYXlvdXRQcm9wZXJ0aWVzKSB7XG4gICAgdmFyIGljb25zID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWydpY29uLWltYWdlJ10pO1xuICAgICAgICBpZiAoIXRleHQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmIChpY29ucy5pbmRleE9mKHRleHQpIDwgMCkge1xuICAgICAgICAgICAgaWNvbnMucHVzaCh0ZXh0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpY29ucztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlc29sdmVUb2tlbnMgPSByZXF1aXJlKCcuLi91dGlsL3Rva2VuJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVzb2x2ZVRleHQ7XG5cbi8qKlxuICogRm9yIGFuIGFycmF5IG9mIGZlYXR1cmVzIGRldGVybWluZSB3aGF0IGdseXBoIHJhbmdlcyBuZWVkIHRvIGJlIGxvYWRlZFxuICogYW5kIGFwcGx5IGFueSB0ZXh0IHByZXByb2Nlc3NpbmcuIFRoZSByZW1haW5pbmcgdXNlcnMgb2YgdGV4dCBzaG91bGRcbiAqIHVzZSB0aGUgYHRleHRGZWF0dXJlc2Aga2V5IHJldHVybmVkIGJ5IHRoaXMgZnVuY3Rpb24gcmF0aGVyIHRoYW4gYWNjZXNzaW5nXG4gKiBmZWF0dXJlIHRleHQgZGlyZWN0bHkuXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiByZXNvbHZlVGV4dChmZWF0dXJlcywgbGF5b3V0UHJvcGVydGllcywgZ2x5cGhzKSB7XG4gICAgdmFyIHRleHRGZWF0dXJlcyA9IFtdO1xuICAgIHZhciBjb2RlcG9pbnRzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgZmwgPSBmZWF0dXJlcy5sZW5ndGg7IGkgPCBmbDsgaSsrKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gcmVzb2x2ZVRva2VucyhmZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LWZpZWxkJ10pO1xuICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgIHRleHRGZWF0dXJlc1tpXSA9IG51bGw7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0ID0gdGV4dC50b1N0cmluZygpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBsYXlvdXRQcm9wZXJ0aWVzWyd0ZXh0LXRyYW5zZm9ybSddO1xuICAgICAgICBpZiAodHJhbnNmb3JtID09PSAndXBwZXJjYXNlJykge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQudG9Mb2NhbGVVcHBlckNhc2UoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2Zvcm0gPT09ICdsb3dlcmNhc2UnKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpsID0gdGV4dC5sZW5ndGg7IGogPCBqbDsgaisrKSB7XG4gICAgICAgICAgICBjb2RlcG9pbnRzLnB1c2godGV4dC5jaGFyQ29kZUF0KGopKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIGluZGV4ZXMgb2YgZmVhdHVyZXMgd2l0aCB0ZXh0LlxuICAgICAgICB0ZXh0RmVhdHVyZXNbaV0gPSB0ZXh0O1xuICAgIH1cblxuICAgIC8vIGdldCBhIGxpc3Qgb2YgdW5pcXVlIGNvZGVwb2ludHMgd2UgYXJlIG1pc3NpbmdcbiAgICBjb2RlcG9pbnRzID0gdW5pcShjb2RlcG9pbnRzLCBnbHlwaHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dEZlYXR1cmVzOiB0ZXh0RmVhdHVyZXMsXG4gICAgICAgIGNvZGVwb2ludHM6IGNvZGVwb2ludHNcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB1bmlxKGlkcywgYWxyZWFkeUhhdmUpIHtcbiAgICB2YXIgdSA9IFtdO1xuICAgIHZhciBsYXN0O1xuICAgIGlkcy5zb3J0KHNvcnROdW1iZXJzKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaWRzW2ldICE9PSBsYXN0KSB7XG4gICAgICAgICAgICBsYXN0ID0gaWRzW2ldO1xuICAgICAgICAgICAgaWYgKCFhbHJlYWR5SGF2ZVtsYXN0XSkgdS5wdXNoKGlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHU7XG59XG5cbmZ1bmN0aW9uIHNvcnROdW1iZXJzKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNoYXBlVGV4dDogc2hhcGVUZXh0LFxuICAgIHNoYXBlSWNvbjogc2hhcGVJY29uXG59O1xuXG5cbi8vIFRoZSBwb3NpdGlvbiBvZiBhIGdseXBoIHJlbGF0aXZlIHRvIHRoZSB0ZXh0J3MgYW5jaG9yIHBvaW50LlxuZnVuY3Rpb24gUG9zaXRpb25lZEdseXBoKGNvZGVQb2ludCwgeCwgeSwgZ2x5cGgpIHtcbiAgICB0aGlzLmNvZGVQb2ludCA9IGNvZGVQb2ludDtcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG4gICAgdGhpcy5nbHlwaCA9IGdseXBoO1xufVxuXG4vLyBBIGNvbGxlY3Rpb24gb2YgcG9zaXRpb25lZCBnbHlwaHMgYW5kIHNvbWUgbWV0YWRhdGFcbmZ1bmN0aW9uIFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5wb3NpdGlvbmVkR2x5cGhzID0gcG9zaXRpb25lZEdseXBocztcbiAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICB0aGlzLmJvdHRvbSA9IGJvdHRvbTtcbiAgICB0aGlzLmxlZnQgPSBsZWZ0O1xuICAgIHRoaXMucmlnaHQgPSByaWdodDtcbn1cblxuZnVuY3Rpb24gc2hhcGVUZXh0KHRleHQsIGdseXBocywgbWF4V2lkdGgsIGxpbmVIZWlnaHQsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSwgc3BhY2luZywgdHJhbnNsYXRlKSB7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IFtdO1xuICAgIHZhciBzaGFwaW5nID0gbmV3IFNoYXBpbmcocG9zaXRpb25lZEdseXBocywgdHJhbnNsYXRlWzFdLCB0cmFuc2xhdGVbMV0sIHRyYW5zbGF0ZVswXSwgdHJhbnNsYXRlWzBdKTtcblxuICAgIC8vIHRoZSB5IG9mZnNldCAqc2hvdWxkKiBiZSBwYXJ0IG9mIHRoZSBmb250IG1ldGFkYXRhXG4gICAgdmFyIHlPZmZzZXQgPSAtMTc7XG5cbiAgICB2YXIgeCA9IHRyYW5zbGF0ZVswXTtcbiAgICB2YXIgeSA9IHRyYW5zbGF0ZVsxXSArIHlPZmZzZXQ7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNvZGVQb2ludCA9IHRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgdmFyIGdseXBoID0gZ2x5cGhzW2NvZGVQb2ludF07XG5cbiAgICAgICAgaWYgKCFnbHlwaCkgY29udGludWU7XG5cbiAgICAgICAgcG9zaXRpb25lZEdseXBocy5wdXNoKG5ldyBQb3NpdGlvbmVkR2x5cGgoY29kZVBvaW50LCB4LCB5LCBnbHlwaCkpO1xuICAgICAgICB4ICs9IGdseXBoLmFkdmFuY2UgKyBzcGFjaW5nO1xuICAgIH1cblxuICAgIGlmICghcG9zaXRpb25lZEdseXBocy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSk7XG5cbiAgICByZXR1cm4gc2hhcGluZztcbn1cblxudmFyIGJyZWFrYWJsZSA9IHsgMzI6IHRydWUgfTsgLy8gQ3VycmVudGx5IG9ubHkgYnJlYWtzIGF0IHJlZ3VsYXIgc3BhY2VzXG5cbmZ1bmN0aW9uIGxpbmV3cmFwKHNoYXBpbmcsIGdseXBocywgbGluZUhlaWdodCwgbWF4V2lkdGgsIGhvcml6b250YWxBbGlnbiwgdmVydGljYWxBbGlnbiwganVzdGlmeSkge1xuICAgIHZhciBsYXN0U2FmZUJyZWFrID0gbnVsbDtcblxuICAgIHZhciBsZW5ndGhCZWZvcmVDdXJyZW50TGluZSA9IDA7XG4gICAgdmFyIGxpbmVTdGFydEluZGV4ID0gMDtcbiAgICB2YXIgbGluZSA9IDA7XG5cbiAgICB2YXIgbWF4TGluZUxlbmd0aCA9IDA7XG5cbiAgICB2YXIgcG9zaXRpb25lZEdseXBocyA9IHNoYXBpbmcucG9zaXRpb25lZEdseXBocztcblxuICAgIGlmIChtYXhXaWR0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9uZWRHbHlwaHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbmVkR2x5cGggPSBwb3NpdGlvbmVkR2x5cGhzW2ldO1xuXG4gICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGgueCAtPSBsZW5ndGhCZWZvcmVDdXJyZW50TGluZTtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRHbHlwaC55ICs9IGxpbmVIZWlnaHQgKiBsaW5lO1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb25lZEdseXBoLnggPiBtYXhXaWR0aCAmJiBsYXN0U2FmZUJyZWFrICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGluZUxlbmd0aCA9IHBvc2l0aW9uZWRHbHlwaHNbbGFzdFNhZmVCcmVhayArIDFdLng7XG4gICAgICAgICAgICAgICAgbWF4TGluZUxlbmd0aCA9IE1hdGgubWF4KGxpbmVMZW5ndGgsIG1heExpbmVMZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IGxhc3RTYWZlQnJlYWsgKyAxOyBrIDw9IGk7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbmVkR2x5cGhzW2tdLnkgKz0gbGluZUhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25lZEdseXBoc1trXS54IC09IGxpbmVMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGp1c3RpZnkpIHtcbiAgICAgICAgICAgICAgICAgICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgbGFzdFNhZmVCcmVhayAtIDEsIGp1c3RpZnkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxpbmVTdGFydEluZGV4ID0gbGFzdFNhZmVCcmVhayArIDE7XG4gICAgICAgICAgICAgICAgbGFzdFNhZmVCcmVhayA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGVuZ3RoQmVmb3JlQ3VycmVudExpbmUgKz0gbGluZUxlbmd0aDtcbiAgICAgICAgICAgICAgICBsaW5lKys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChicmVha2FibGVbcG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0pIHtcbiAgICAgICAgICAgICAgICBsYXN0U2FmZUJyZWFrID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYXN0UG9zaXRpb25lZEdseXBoID0gcG9zaXRpb25lZEdseXBoc1twb3NpdGlvbmVkR2x5cGhzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBsYXN0TGluZUxlbmd0aCA9IGxhc3RQb3NpdGlvbmVkR2x5cGgueCArIGdseXBoc1tsYXN0UG9zaXRpb25lZEdseXBoLmNvZGVQb2ludF0uYWR2YW5jZTtcbiAgICBtYXhMaW5lTGVuZ3RoID0gTWF0aC5tYXgobWF4TGluZUxlbmd0aCwgbGFzdExpbmVMZW5ndGgpO1xuXG4gICAgdmFyIGhlaWdodCA9IChsaW5lICsgMSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBsaW5lU3RhcnRJbmRleCwgcG9zaXRpb25lZEdseXBocy5sZW5ndGggLSAxLCBqdXN0aWZ5KTtcbiAgICBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBib3VuZGluZyBib3hcbiAgICBzaGFwaW5nLnRvcCArPSAtdmVydGljYWxBbGlnbiAqIGhlaWdodDtcbiAgICBzaGFwaW5nLmJvdHRvbSA9IHNoYXBpbmcudG9wICsgaGVpZ2h0O1xuICAgIHNoYXBpbmcubGVmdCArPSAtaG9yaXpvbnRhbEFsaWduICogbWF4TGluZUxlbmd0aDtcbiAgICBzaGFwaW5nLnJpZ2h0ID0gc2hhcGluZy5sZWZ0ICsgbWF4TGluZUxlbmd0aDtcbn1cblxuZnVuY3Rpb24ganVzdGlmeUxpbmUocG9zaXRpb25lZEdseXBocywgZ2x5cGhzLCBzdGFydCwgZW5kLCBqdXN0aWZ5KSB7XG4gICAgdmFyIGxhc3RBZHZhbmNlID0gZ2x5cGhzW3Bvc2l0aW9uZWRHbHlwaHNbZW5kXS5jb2RlUG9pbnRdLmFkdmFuY2U7XG4gICAgdmFyIGxpbmVJbmRlbnQgPSAocG9zaXRpb25lZEdseXBoc1tlbmRdLnggKyBsYXN0QWR2YW5jZSkgKiBqdXN0aWZ5O1xuXG4gICAgZm9yICh2YXIgaiA9IHN0YXJ0OyBqIDw9IGVuZDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCAtPSBsaW5lSW5kZW50O1xuICAgIH1cblxufVxuXG5mdW5jdGlvbiBhbGlnbihwb3NpdGlvbmVkR2x5cGhzLCBqdXN0aWZ5LCBob3Jpem9udGFsQWxpZ24sIHZlcnRpY2FsQWxpZ24sIG1heExpbmVMZW5ndGgsIGxpbmVIZWlnaHQsIGxpbmUpIHtcbiAgICB2YXIgc2hpZnRYID0gKGp1c3RpZnkgLSBob3Jpem9udGFsQWxpZ24pICogbWF4TGluZUxlbmd0aDtcbiAgICB2YXIgc2hpZnRZID0gKC12ZXJ0aWNhbEFsaWduICogKGxpbmUgKyAxKSArIDAuNSkgKiBsaW5lSGVpZ2h0O1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwb3NpdGlvbmVkR2x5cGhzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueCArPSBzaGlmdFg7XG4gICAgICAgIHBvc2l0aW9uZWRHbHlwaHNbal0ueSArPSBzaGlmdFk7XG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIHNoYXBlSWNvbihpbWFnZSwgbGF5b3V0KSB7XG4gICAgaWYgKCFpbWFnZSB8fCAhaW1hZ2UucmVjdCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZHggPSBsYXlvdXRbJ2ljb24tb2Zmc2V0J11bMF07XG4gICAgdmFyIGR5ID0gbGF5b3V0WydpY29uLW9mZnNldCddWzFdO1xuICAgIHZhciB4MSA9IGR4IC0gaW1hZ2Uud2lkdGggLyAyO1xuICAgIHZhciB4MiA9IHgxICsgaW1hZ2Uud2lkdGg7XG4gICAgdmFyIHkxID0gZHkgLSBpbWFnZS5oZWlnaHQgLyAyO1xuICAgIHZhciB5MiA9IHkxICsgaW1hZ2UuaGVpZ2h0O1xuXG4gICAgcmV0dXJuIG5ldyBQb3NpdGlvbmVkSWNvbihpbWFnZSwgeTEsIHkyLCB4MSwgeDIpO1xufVxuXG5mdW5jdGlvbiBQb3NpdGlvbmVkSWNvbihpbWFnZSwgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0KSB7XG4gICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgIHRoaXMudG9wID0gdG9wO1xuICAgIHRoaXMuYm90dG9tID0gYm90dG9tO1xuICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQmluUGFjayA9IHJlcXVpcmUoJy4vYmluX3BhY2snKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTcHJpdGVBdGxhcztcbmZ1bmN0aW9uIFNwcml0ZUF0bGFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICB0aGlzLmJpbiA9IG5ldyBCaW5QYWNrKHdpZHRoLCBoZWlnaHQpO1xuICAgIHRoaXMuaW1hZ2VzID0ge307XG4gICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0dXJlID0gMDsgLy8gV2ViR0wgSURcbiAgICB0aGlzLmZpbHRlciA9IDA7IC8vIFdlYkdMIElEXG4gICAgdGhpcy5waXhlbFJhdGlvID0gMTtcbiAgICB0aGlzLmRpcnR5ID0gdHJ1ZTtcbn1cblxuU3ByaXRlQXRsYXMucHJvdG90eXBlID0ge1xuICAgIGdldCBkZWJ1ZygpIHtcbiAgICAgICAgcmV0dXJuICdjYW52YXMnIGluIHRoaXM7XG4gICAgfSxcbiAgICBzZXQgZGVidWcodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgfSBlbHNlIGlmICghdmFsdWUgJiYgdGhpcy5jYW52YXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY3R4O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FudmFzO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKG5ld1JhdGlvKSB7XG4gICAgaWYgKHRoaXMucGl4ZWxSYXRpbyA9PT0gbmV3UmF0aW8pIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBvbGRSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbztcbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBuZXdSYXRpbztcblxuICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGggKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLmRhdGE7XG5cbiAgICAgICAgdGhpcy5kYXRhID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICAgICAgdGhpcy50ZXh0dXJlID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIG9sZFdpZHRoID0gdGhpcy53aWR0aCAqIG9sZFJhdGlvO1xuICAgICAgICB2YXIgb2xkSGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBvbGRSYXRpbztcbiAgICAgICAgdmFyIG5ld1dpZHRoID0gdGhpcy53aWR0aCAqIG5ld1JhdGlvO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gdGhpcy5oZWlnaHQgKiBuZXdSYXRpbztcblxuICAgICAgICAvLyBCYXNpYyBpbWFnZSBzY2FsaW5nLiBUT0RPOiBSZXBsYWNlIHRoaXMgd2l0aCBiZXR0ZXIgaW1hZ2Ugc2NhbGluZy5cbiAgICAgICAgdmFyIG5ld0ltYWdlID0gdGhpcy5kYXRhO1xuICAgICAgICB2YXIgb2xkSW1hZ2UgPSBvbGREYXRhO1xuXG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgbmV3SGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgIHZhciBvbGRZT2Zmc2V0ID0gTWF0aC5mbG9vcigoeSAqIG9sZEhlaWdodCkgLyBuZXdIZWlnaHQpICogb2xkV2lkdGg7XG4gICAgICAgICAgICB2YXIgbmV3WU9mZnNldCA9IHkgKiBuZXdXaWR0aDtcbiAgICAgICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgbmV3V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIHZhciBvbGRYID0gTWF0aC5mbG9vcigoeCAqIG9sZFdpZHRoKSAvIG5ld1dpZHRoKTtcbiAgICAgICAgICAgICAgICBuZXdJbWFnZVtuZXdZT2Zmc2V0ICsgeF0gPSBvbGRJbWFnZVtvbGRZT2Zmc2V0ICsgb2xkWF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBvbGREYXRhID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXJ0eSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGlydHk7XG59O1xuXG5mdW5jdGlvbiBjb3B5Qml0bWFwKHNyYywgc3JjU3RyaWRlLCBzcmNYLCBzcmNZLCBkc3QsIGRzdFN0cmlkZSwgZHN0WCwgZHN0WSwgd2lkdGgsIGhlaWdodCwgd3JhcCkge1xuICAgIHZhciBzcmNJID0gc3JjWSAqIHNyY1N0cmlkZSArIHNyY1g7XG4gICAgdmFyIGRzdEkgPSBkc3RZICogZHN0U3RyaWRlICsgZHN0WDtcbiAgICB2YXIgeCwgeTtcblxuICAgIGlmICh3cmFwKSB7XG4gICAgICAgIC8vIGFkZCAxIHBpeGVsIHdyYXBwZWQgcGFkZGluZyBvbiBlYWNoIHNpZGUgb2YgdGhlIGltYWdlXG4gICAgICAgIGRzdEkgLT0gZHN0U3RyaWRlO1xuICAgICAgICBmb3IgKHkgPSAtMTsgeSA8PSBoZWlnaHQ7IHkrKywgc3JjSSA9ICgoeSArIGhlaWdodCkgJSBoZWlnaHQgKyBzcmNZKSAqIHNyY1N0cmlkZSArIHNyY1gsIGRzdEkgKz0gZHN0U3RyaWRlKSB7XG4gICAgICAgICAgICBmb3IgKHggPSAtMTsgeCA8PSB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgKCh4ICsgd2lkdGgpICUgd2lkdGgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICh5ID0gMDsgeSA8IGhlaWdodDsgeSsrLCBzcmNJICs9IHNyY1N0cmlkZSwgZHN0SSArPSBkc3RTdHJpZGUpIHtcbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgZHN0W2RzdEkgKyB4XSA9IHNyY1tzcmNJICsgeF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZUltYWdlID0gZnVuY3Rpb24ocGl4ZWxXaWR0aCwgcGl4ZWxIZWlnaHQpIHtcblxuICAgIC8vIEluY3JlYXNlIHRvIG5leHQgbnVtYmVyIGRpdmlzaWJsZSBieSA0LCBidXQgYXQgbGVhc3QgMS5cbiAgICAvLyBUaGlzIGlzIHNvIHdlIGNhbiBzY2FsZSBkb3duIHRoZSB0ZXh0dXJlIGNvb3JkaW5hdGVzIGFuZCBwYWNrIHRoZW1cbiAgICAvLyBpbnRvIDIgYnl0ZXMgcmF0aGVyIHRoYW4gNCBieXRlcy5cbiAgICAvLyBQYWQgaWNvbnMgdG8gcHJldmVudCB0aGVtIGZyb20gcG9sbHV0aW5nIG5laWdoYm91cnMgZHVyaW5nIGxpbmVhciBpbnRlcnBvbGF0aW9uXG4gICAgdmFyIHBhZGRpbmcgPSAyO1xuICAgIHZhciBwYWNrV2lkdGggPSBwaXhlbFdpZHRoICsgcGFkZGluZyArICg0IC0gKHBpeGVsV2lkdGggKyBwYWRkaW5nKSAlIDQpO1xuICAgIHZhciBwYWNrSGVpZ2h0ID0gcGl4ZWxIZWlnaHQgKyBwYWRkaW5nICsgKDQgLSAocGl4ZWxIZWlnaHQgKyBwYWRkaW5nKSAlIDQpOy8vICsgNDtcblxuICAgIC8vIFdlIGhhdmUgdG8gYWxsb2NhdGUgYSBuZXcgYXJlYSBpbiB0aGUgYmluLCBhbmQgc3RvcmUgYW4gZW1wdHkgaW1hZ2UgaW4gaXQuXG4gICAgLy8gQWRkIGEgMXB4IGJvcmRlciBhcm91bmQgZXZlcnkgaW1hZ2UuXG4gICAgdmFyIHJlY3QgPSB0aGlzLmJpbi5hbGxvY2F0ZShwYWNrV2lkdGgsIHBhY2tIZWlnaHQpO1xuICAgIGlmIChyZWN0LncgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgfVxuXG4gICAgcmVjdC5vcmlnaW5hbFdpZHRoID0gcGl4ZWxXaWR0aDtcbiAgICByZWN0Lm9yaWdpbmFsSGVpZ2h0ID0gcGl4ZWxIZWlnaHQ7XG5cbiAgICByZXR1cm4gcmVjdDtcbn07XG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uKG5hbWUsIHdyYXApIHtcbiAgICBpZiAodGhpcy5pbWFnZXNbbmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzW25hbWVdO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5zcHJpdGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHBvcyA9IHRoaXMuc3ByaXRlLmdldFNwcml0ZVBvc2l0aW9uKG5hbWUpO1xuICAgIGlmICghcG9zLndpZHRoIHx8ICFwb3MuaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciB3aWR0aCA9IHBvcy53aWR0aCAvIHBvcy5waXhlbFJhdGlvO1xuICAgIHZhciBoZWlnaHQgPSBwb3MuaGVpZ2h0IC8gcG9zLnBpeGVsUmF0aW87XG4gICAgdmFyIHJlY3QgPSB0aGlzLmFsbG9jYXRlSW1hZ2Uod2lkdGgsIGhlaWdodCk7XG4gICAgaWYgKHJlY3QudyA9PT0gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICB9XG5cbiAgICB2YXIgaW1hZ2UgPSBuZXcgQXRsYXNJbWFnZShyZWN0LCB3aWR0aCwgaGVpZ2h0LCBwb3Muc2RmKTtcbiAgICB0aGlzLmltYWdlc1tuYW1lXSA9IGltYWdlO1xuXG4gICAgdGhpcy5jb3B5KHJlY3QsIHBvcywgd3JhcCk7XG5cbiAgICByZXR1cm4gaW1hZ2U7XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKG5hbWUsIHJlcGVhdGluZykge1xuICAgIHZhciBpbWFnZSA9IHRoaXMuZ2V0SW1hZ2UobmFtZSwgcmVwZWF0aW5nKTtcbiAgICB2YXIgcmVjdCA9IGltYWdlICYmIGltYWdlLnJlY3Q7XG5cbiAgICBpZiAoIXJlY3QpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB0aGUgaW1hZ2UgaXMgcmVwZWF0aW5nLCBnZXQgdGhlIGNvcnJlY3QgcG9zaXRpb24gb2YgdGhlIGltYWdlLCByYXRoZXIgdGhhbiB0aGVcbiAgICAvLyBvbmUgcm91bmRlZCB1cCB0byA0IHBpeGVscy5cbiAgICB2YXIgd2lkdGggPSByZXBlYXRpbmcgPyBpbWFnZS53aWR0aCA6IHJlY3QudztcbiAgICB2YXIgaGVpZ2h0ID0gcmVwZWF0aW5nID8gaW1hZ2UuaGVpZ2h0IDogcmVjdC5oO1xuICAgIHZhciBwYWRkaW5nID0gMTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHNpemU6IFt3aWR0aCwgaGVpZ2h0XSxcbiAgICAgICAgdGw6IFsocmVjdC54ICsgcGFkZGluZykgICAgICAgICAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nKSAgICAgICAgICAvIHRoaXMuaGVpZ2h0XSxcbiAgICAgICAgYnI6IFsocmVjdC54ICsgcGFkZGluZyArIHdpZHRoKSAvIHRoaXMud2lkdGgsIChyZWN0LnkgKyBwYWRkaW5nICsgaGVpZ2h0KSAvIHRoaXMuaGVpZ2h0XVxuICAgIH07XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5kYXRhKSB7XG4gICAgICAgIHZhciB3ID0gTWF0aC5mbG9vcih0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdmFyIGggPSBNYXRoLmZsb29yKHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQzMkFycmF5KHcgKiBoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cblNwcml0ZUF0bGFzLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24oZHN0LCBzcmMsIHdyYXApIHtcbiAgICAvLyBpZiAoIXNwcml0ZS0+cmFzdGVyKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnNwcml0ZS5pbWcuZGF0YSkgcmV0dXJuO1xuICAgIHZhciBzcmNJbWcgPSBuZXcgVWludDMyQXJyYXkodGhpcy5zcHJpdGUuaW1nLmRhdGEuYnVmZmVyKTtcblxuICAgIHRoaXMuYWxsb2NhdGUoKTtcbiAgICB2YXIgZHN0SW1nID0gdGhpcy5kYXRhO1xuXG4gICAgdmFyIHBhZGRpbmcgPSAxO1xuXG4gICAgY29weUJpdG1hcChcbiAgICAgICAgLyogc291cmNlIGJ1ZmZlciAqLyAgc3JjSW1nLFxuICAgICAgICAvKiBzb3VyY2Ugc3RyaWRlICovICB0aGlzLnNwcml0ZS5pbWcud2lkdGgsXG4gICAgICAgIC8qIHNvdXJjZSB4ICovICAgICAgIHNyYy54LFxuICAgICAgICAvKiBzb3VyY2UgeSAqLyAgICAgICBzcmMueSxcbiAgICAgICAgLyogZGVzdCBidWZmZXIgKi8gICAgZHN0SW1nLFxuICAgICAgICAvKiBkZXN0IHN0cmlkZSAqLyAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLFxuICAgICAgICAvKiBkZXN0IHggKi8gICAgICAgICAoZHN0LnggKyBwYWRkaW5nKSAqIHRoaXMucGl4ZWxSYXRpbyxcbiAgICAgICAgLyogZGVzdCB5ICovICAgICAgICAgKGRzdC55ICsgcGFkZGluZykgKiB0aGlzLnBpeGVsUmF0aW8sXG4gICAgICAgIC8qIGljb24gZGltZW5zaW9uICovIHNyYy53aWR0aCxcbiAgICAgICAgLyogaWNvbiBkaW1lbnNpb24gKi8gc3JjLmhlaWdodCxcbiAgICAgICAgLyogd3JhcCAqLyB3cmFwXG4gICAgKTtcblxuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLnNldFNwcml0ZSA9IGZ1bmN0aW9uKHNwcml0ZSkge1xuICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xufTtcblxuU3ByaXRlQXRsYXMucHJvdG90eXBlLmFkZEljb25zID0gZnVuY3Rpb24oaWNvbnMsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpY29ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmdldEltYWdlKGljb25zW2ldKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCB0aGlzLmltYWdlcyk7XG59O1xuXG5TcHJpdGVBdGxhcy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKGdsLCBsaW5lYXIpIHtcbiAgICB2YXIgZmlyc3QgPSBmYWxzZTtcbiAgICBpZiAoIXRoaXMudGV4dHVyZSkge1xuICAgICAgICB0aGlzLnRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgZmlyc3QgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZSk7XG4gICAgfVxuXG4gICAgdmFyIGZpbHRlclZhbCA9IGxpbmVhciA/IGdsLkxJTkVBUiA6IGdsLk5FQVJFU1Q7XG4gICAgaWYgKGZpbHRlclZhbCAhPT0gdGhpcy5maWx0ZXIpIHtcbiAgICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGZpbHRlclZhbCk7XG4gICAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBmaWx0ZXJWYWwpO1xuICAgICAgICB0aGlzLmZpbHRlciA9IGZpbHRlclZhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kaXJ0eSkge1xuICAgICAgICB0aGlzLmFsbG9jYXRlKCk7XG5cbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIGdsLlRFWFRVUkVfMkQsIC8vIGVudW0gdGFyZ2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW5kIGxldmVsXG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gaW5kIGludGVybmFsZm9ybWF0XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgLy8gR0xzaXplaSB3aWR0aFxuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvLCAvLyBHTHNpemVpIGhlaWdodFxuICAgICAgICAgICAgICAgIDAsIC8vIGluZCBib3JkZXJcbiAgICAgICAgICAgICAgICBnbC5SR0JBLCAvLyBlbnVtIGZvcm1hdFxuICAgICAgICAgICAgICAgIGdsLlVOU0lHTkVEX0JZVEUsIC8vIGVudW0gdHlwZVxuICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KHRoaXMuZGF0YS5idWZmZXIpIC8vIE9iamVjdCBkYXRhXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2wudGV4U3ViSW1hZ2UyRChcbiAgICAgICAgICAgICAgICBnbC5URVhUVVJFXzJELCAvLyBlbnVtIHRhcmdldFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCBsZXZlbFxuICAgICAgICAgICAgICAgIDAsIC8vIGludCB4b2Zmc2V0XG4gICAgICAgICAgICAgICAgMCwgLy8gaW50IHlvZmZzZXRcbiAgICAgICAgICAgICAgICB0aGlzLndpZHRoICogdGhpcy5waXhlbFJhdGlvLCAvLyBsb25nIHdpZHRoXG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8sIC8vIGxvbmcgaGVpZ2h0XG4gICAgICAgICAgICAgICAgZ2wuUkdCQSwgLy8gZW51bSBmb3JtYXRcbiAgICAgICAgICAgICAgICBnbC5VTlNJR05FRF9CWVRFLCAvLyBlbnVtIHR5cGVcbiAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheSh0aGlzLmRhdGEuYnVmZmVyKSAvLyBPYmplY3QgcGl4ZWxzXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuXG4gICAgICAgIC8vIERFQlVHXG4gICAgICAgIGlmICh0aGlzLmN0eCkge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLmN0eC5nZXRJbWFnZURhdGEoMCwgMCwgdGhpcy53aWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgdGhpcy5oZWlnaHQgKiB0aGlzLnBpeGVsUmF0aW8pO1xuICAgICAgICAgICAgZGF0YS5kYXRhLnNldChuZXcgVWludDhDbGFtcGVkQXJyYXkodGhpcy5kYXRhLmJ1ZmZlcikpO1xuICAgICAgICAgICAgdGhpcy5jdHgucHV0SW1hZ2VEYXRhKGRhdGEsIDAsIDApO1xuXG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9ICdyZWQnO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aGlzLmJpbi5mcmVlLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSB0aGlzLmJpbi5mcmVlW2tdO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVJlY3QoZnJlZS54ICogdGhpcy5waXhlbFJhdGlvLCBmcmVlLnkgKiB0aGlzLnBpeGVsUmF0aW8sIGZyZWUudyAqIHRoaXMucGl4ZWxSYXRpbywgZnJlZS5oICogdGhpcy5waXhlbFJhdGlvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFTkQgREVCVUdcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBBdGxhc0ltYWdlKHJlY3QsIHdpZHRoLCBoZWlnaHQsIHNkZikge1xuICAgIHRoaXMucmVjdCA9IHJlY3Q7XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIHRoaXMuc2RmID0gc2RmO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIGludGVycG9sYXRlID0gcmVxdWlyZSgnLi4vdXRpbC9pbnRlcnBvbGF0ZScpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuLi91dGlsL2Jyb3dzZXInKTtcbnZhciBMYXRMbmcgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZycpO1xudmFyIExhdExuZ0JvdW5kcyA9IHJlcXVpcmUoJy4uL2dlby9sYXRfbG5nX2JvdW5kcycpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYW1lcmFPcHRpb25zXG4gKiBAcHJvcGVydHkge0FycmF5fSBbY2VudGVyXSBMYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIChwYXNzZWQgYXMgYFtsYXQsIGxuZ11gKVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6b29tXSBNYXAgem9vbSBsZXZlbFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtiZWFyaW5nXSBNYXAgcm90YXRpb24gYmVhcmluZyBpbiBkZWdyZWVzIGNvdW50ZXItY2xvY2t3aXNlIGZyb20gbm9ydGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcGl0Y2hdIFRoZSBhbmdsZSBhdCB3aGljaCB0aGUgY2FtZXJhIGlzIGxvb2tpbmcgYXQgdGhlIGdyb3VuZFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gW0FuaW1hdGlvbk9wdGlvbnNdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTUwMF0gTnVtYmVyIGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gW2Vhc2luZ11cbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IFtvZmZzZXQ9WzAsMF1dIHBvaW50LCBvcmlnaW4gb2YgbW92ZW1lbnQgcmVsYXRpdmUgdG8gbWFwIGNlbnRlclxuICogQHByb3BlcnR5IHtib29sZWFufSBbYW5pbWF0ZT10cnVlXSBXaGVuIHNldCB0byBmYWxzZSwgbm8gYW5pbWF0aW9uIGhhcHBlbnNcbiAqL1xuXG52YXIgQ2FtZXJhID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHt9O1xuXG51dGlsLmV4dGVuZChDYW1lcmEucHJvdG90eXBlLCAvKiogQGxlbmRzIE1hcC5wcm90b3R5cGUgKi97XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IHZpZXcgZ2VvZ3JhcGhpY2FsIHBvaW50LlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgZ2V0Q2VudGVyOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudHJhbnNmb3JtLmNlbnRlcjsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgbG9jYXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjZW50ZXIgTGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSAocGFzc2VkIGFzIGBbbGF0LCBsbmddYClcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5zZXRDZW50ZXIoWy03NCwgMzhdKTtcbiAgICAgKi9cbiAgICBzZXRDZW50ZXI6IGZ1bmN0aW9uKGNlbnRlcikge1xuICAgICAgICB0aGlzLmp1bXBUbyh7Y2VudGVyOiBjZW50ZXJ9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUGFuIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgcGl4ZWxzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvZmZzZXQgW3gsIHldXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHBhbkJ5OiBmdW5jdGlvbihvZmZzZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5wYW5Ubyh0aGlzLnRyYW5zZm9ybS5jZW50ZXIsIHV0aWwuZXh0ZW5kKHtvZmZzZXQ6IFBvaW50LmNvbnZlcnQob2Zmc2V0KS5tdWx0KC0xKX0sIG9wdGlvbnMpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFBhbiB0byBhIGNlcnRhaW4gbG9jYXRpb24gd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBsYXRsbmcgYSBgTGF0TG5nYCBvYmplY3RcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcGFuVG86IGZ1bmN0aW9uKGxhdGxuZywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLnN0b3AoKTtcblxuICAgICAgICBsYXRsbmcgPSBMYXRMbmcuY29udmVydChsYXRsbmcpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuICAgICAgICAgICAgZWFzaW5nOiB1dGlsLmVhc2UsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLnJvdGF0ZSgtdHIuYW5nbGUpLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGxhdGxuZykuc3ViKG9mZnNldCk7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSB0ci51bnByb2plY3QoZnJvbS5hZGQodG8uc3ViKGZyb20pLm11bHQoaykpKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgem9vbVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0Wm9vbTogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLnRyYW5zZm9ybS56b29tOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIG1hcCB6b29tLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3pvb206IHpvb219KWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBNYXAgem9vbSBsZXZlbFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gem9vbSB0aGUgbWFwIHRvIDVcbiAgICAgKiBtYXAuc2V0Wm9vbSg1KTtcbiAgICAgKi9cbiAgICBzZXRab29tOiBmdW5jdGlvbih6b29tKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHt6b29tOiB6b29tfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRvIGEgY2VydGFpbiB6b29tIGxldmVsIHdpdGggZWFzaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHpvb21cbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbVRvOiBmdW5jdGlvbih6b29tLCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBkdXJhdGlvbjogNTAwXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIG9wdGlvbnMuZWFzaW5nID0gdGhpcy5fdXBkYXRlRWFzaW5nKG9wdGlvbnMuZHVyYXRpb24sIHpvb20sIG9wdGlvbnMuZWFzaW5nKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLmNlbnRlcixcbiAgICAgICAgICAgIHN0YXJ0Wm9vbSA9IHRyLnpvb207XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSkgb3B0aW9ucy5kdXJhdGlvbiA9IDA7XG5cbiAgICAgICAgaWYgKCF0aGlzLnpvb21pbmcpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRab29tQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0Wm9vbSwgem9vbSwgayksIGFyb3VuZCk7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmUnKS5maXJlKCd6b29tJyk7XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5lYXNlID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmR1cmF0aW9uID49IDIwMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5kdXJhdGlvbiA8IDIwMCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX29uWm9vbUVuZCk7XG4gICAgICAgICAgICB0aGlzLl9vblpvb21FbmQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCAyMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFpvb20gaW4gYnkgMSBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIHtBbmltYXRpb25PcHRpb25zfVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIHpvb21JbjogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSArIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBab29tIG91dCBieSAxIGxldmVsXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgem9vbU91dDogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICB0aGlzLnpvb21Ubyh0aGlzLmdldFpvb20oKSAtIDEsIG9wdGlvbnMpO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBiZWFyaW5nIGluIGRlZ3JlZXNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGdldEJlYXJpbmc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0uYmVhcmluZzsgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBtYXAgcm90YXRpb24uIEVxdWl2YWxlbnQgdG8gYGp1bXBUbyh7YmVhcmluZzogYmVhcmluZ30pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiZWFyaW5nIE1hcCByb3RhdGlvbiBiZWFyaW5nIGluIGRlZ3JlZXMgY291bnRlci1jbG9ja3dpc2UgZnJvbSBub3J0aFxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gcm90YXRlIHRoZSBtYXAgdG8gOTAgZGVncmVlc1xuICAgICAqIG1hcC5zZXRCZWFyaW5nKDkwKTtcbiAgICAgKi9cbiAgICBzZXRCZWFyaW5nOiBmdW5jdGlvbihiZWFyaW5nKSB7XG4gICAgICAgIHRoaXMuanVtcFRvKHtiZWFyaW5nOiBiZWFyaW5nfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZSBiZWFyaW5nIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgZGVncmVlcyB3aXRoIGVhc2luZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGJlYXJpbmdcbiAgICAgKiBAcGFyYW0ge0FuaW1hdGlvbk9wdGlvbnN9XG4gICAgICogQGZpcmVzIG1vdmVzdGFydFxuICAgICAqIEBmaXJlcyBtb3ZlZW5kXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgcm90YXRlVG86IGZ1bmN0aW9uKGJlYXJpbmcsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBlYXNpbmc6IHV0aWwuZWFzZVxuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICB2YXIgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIHN0YXJ0ID0gdGhpcy5nZXRCZWFyaW5nKCksXG4gICAgICAgICAgICBhcm91bmQgPSB0ci5jZW50ZXI7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYXJvdW5kKSB7XG4gICAgICAgICAgICBhcm91bmQgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmFyb3VuZCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBiZWFyaW5nID0gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhiZWFyaW5nLCBzdGFydCk7XG5cbiAgICAgICAgdGhpcy5yb3RhdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbihrKSB7XG4gICAgICAgICAgICB0ci5zZXRCZWFyaW5nQXJvdW5kKGludGVycG9sYXRlKHN0YXJ0LCBiZWFyaW5nLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xuICAgICAgICB9LCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtYXAgYmVhcmluZyB0byAwIChub3J0aCkgd2l0aCBlYXNpbmdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QW5pbWF0aW9uT3B0aW9uc31cbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICByZXNldE5vcnRoOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvdGF0ZVRvKDAsIHV0aWwuZXh0ZW5kKHtkdXJhdGlvbjogMTAwMH0sIG9wdGlvbnMpKTtcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgYW5nbGUgaW4gZGVncmVlc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgZ2V0UGl0Y2g6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucGl0Y2g7IH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgbWFwIGFuZ2xlLiBFcXVpdmFsZW50IHRvIGBqdW1wVG8oe3BpdGNoOiBwaXRjaH0pYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXRjaCBUaGUgYW5nbGUgYXQgd2hpY2ggdGhlIGNhbWVyYSBpcyBsb29raW5nIGF0IHRoZSBncm91bmRcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRQaXRjaDogZnVuY3Rpb24ocGl0Y2gpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8oe3BpdGNoOiBwaXRjaH0pO1xuICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAqIFpvb20gdG8gY29udGFpbiBjZXJ0YWluIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJvdW5kcyBbW21pbkxhdCwgbWluTG5nXSwgW21heExhdCwgbWF4TG5nXV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5zcGVlZD0xLjJdIEhvdyBmYXN0IGFuaW1hdGlvbiBvY2N1cnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuY3VydmU9MS40Ml0gSG93IG11Y2ggem9vbWluZyBvdXQgb2NjdXJzIGR1cmluZyBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmVhc2luZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLnBhZGRpbmcgaG93IG11Y2ggcGFkZGluZyB0aGVyZSBpcyBhcm91bmQgdGhlIGdpdmVuIGJvdW5kcyBvbiBlYWNoIHNpZGUgaW4gcGl4ZWxzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMubWF4Wm9vbVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqL1xuICAgIGZpdEJvdW5kczogZnVuY3Rpb24oYm91bmRzLCBvcHRpb25zKSB7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIHBhZGRpbmc6IDAsXG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIG1heFpvb206IEluZmluaXR5XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIGJvdW5kcyA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KGJvdW5kcyk7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFBvaW50LmNvbnZlcnQob3B0aW9ucy5vZmZzZXQpLFxuICAgICAgICAgICAgdHIgPSB0aGlzLnRyYW5zZm9ybSxcbiAgICAgICAgICAgIG53ID0gdHIucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxuICAgICAgICAgICAgc2UgPSB0ci5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aEVhc3QoKSksXG4gICAgICAgICAgICBzaXplID0gc2Uuc3ViKG53KSxcbiAgICAgICAgICAgIHNjYWxlWCA9ICh0ci53aWR0aCAtIG9wdGlvbnMucGFkZGluZyAqIDIgLSBNYXRoLmFicyhvZmZzZXQueCkgKiAyKSAvIHNpemUueCxcbiAgICAgICAgICAgIHNjYWxlWSA9ICh0ci5oZWlnaHQgLSBvcHRpb25zLnBhZGRpbmcgKiAyIC0gTWF0aC5hYnMob2Zmc2V0LnkpICogMikgLyBzaXplLnk7XG5cbiAgICAgICAgb3B0aW9ucy5jZW50ZXIgPSB0ci51bnByb2plY3QobncuYWRkKHNlKS5kaXYoMikpO1xuICAgICAgICBvcHRpb25zLnpvb20gPSBNYXRoLm1pbih0ci5zY2FsZVpvb20odHIuc2NhbGUgKiBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSkpLCBvcHRpb25zLm1heFpvb20pO1xuICAgICAgICBvcHRpb25zLmJlYXJpbmcgPSAwO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zLmxpbmVhciA/XG4gICAgICAgICAgICB0aGlzLmVhc2VUbyhvcHRpb25zKSA6XG4gICAgICAgICAgICB0aGlzLmZseVRvKG9wdGlvbnMpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2UgYW55IGNvbWJpbmF0aW9uIG9mIGNlbnRlciwgem9vbSwgYmVhcmluZywgYW5kIHBpdGNoLCB3aXRob3V0XG4gICAgICogYSB0cmFuc2l0aW9uLiBUaGUgbWFwIHdpbGwgcmV0YWluIHRoZSBjdXJyZW50IHZhbHVlcyBmb3IgYW55IG9wdGlvbnNcbiAgICAgKiBub3QgaW5jbHVkZWQgaW4gYG9wdGlvbnNgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBqdW1wVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgdmFyIHRyID0gdGhpcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICB6b29tQ2hhbmdlZCA9IGZhbHNlLFxuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSBmYWxzZSxcbiAgICAgICAgICAgIHBpdGNoQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICgnY2VudGVyJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB0ci5jZW50ZXIgPSBMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3pvb20nIGluIG9wdGlvbnMgJiYgdHIuem9vbSAhPT0gK29wdGlvbnMuem9vbSkge1xuICAgICAgICAgICAgem9vbUNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuem9vbSA9ICtvcHRpb25zLnpvb207XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2JlYXJpbmcnIGluIG9wdGlvbnMgJiYgdHIuYmVhcmluZyAhPT0gK29wdGlvbnMuYmVhcmluZykge1xuICAgICAgICAgICAgYmVhcmluZ0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgdHIuYmVhcmluZyA9ICtvcHRpb25zLmJlYXJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ3BpdGNoJyBpbiBvcHRpb25zICYmIHRyLnBpdGNoICE9PSArb3B0aW9ucy5waXRjaCkge1xuICAgICAgICAgICAgcGl0Y2hDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyLnBpdGNoID0gK29wdGlvbnMucGl0Y2g7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZScpO1xuXG4gICAgICAgIGlmICh6b29tQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5maXJlKCd6b29tJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYmVhcmluZ0NoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGl0Y2hDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ3BpdGNoJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEVhc2luZyBhbmltYXRpb24gdG8gYSBzcGVjaWZpZWQgbG9jYXRpb24vem9vbS9iZWFyaW5nXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NhbWVyYU9wdGlvbnMrQW5pbWF0aW9uT3B0aW9uc30gb3B0aW9ucyBtYXAgdmlldyBhbmQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgbW92ZXN0YXJ0XG4gICAgICogQGZpcmVzIG1vdmVlbmRcbiAgICAgKiBAcmV0dXJucyB7dGhpc31cbiAgICAgKi9cbiAgICBlYXNlVG86IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG5cbiAgICAgICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHtcbiAgICAgICAgICAgIG9mZnNldDogWzAsIDBdLFxuICAgICAgICAgICAgZHVyYXRpb246IDUwMCxcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCkucm90YXRlKC10ci5hbmdsZSksXG4gICAgICAgICAgICBmcm9tID0gdHIucG9pbnQsXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpLFxuICAgICAgICAgICAgc3RhcnRQaXRjaCA9IHRoaXMuZ2V0UGl0Y2goKTtcblxuICAgICAgICB2YXIgem9vbSA9ICd6b29tJyBpbiBvcHRpb25zID8gK29wdGlvbnMuem9vbSA6IHN0YXJ0Wm9vbTtcbiAgICAgICAgdmFyIGJlYXJpbmcgPSAnYmVhcmluZycgaW4gb3B0aW9ucyA/IHRoaXMuX25vcm1hbGl6ZUJlYXJpbmcob3B0aW9ucy5iZWFyaW5nLCBzdGFydEJlYXJpbmcpIDogc3RhcnRCZWFyaW5nO1xuICAgICAgICB2YXIgcGl0Y2ggPSAncGl0Y2gnIGluIG9wdGlvbnMgPyArb3B0aW9ucy5waXRjaCA6IHN0YXJ0UGl0Y2g7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgdG8gPSAnY2VudGVyJyBpbiBvcHRpb25zID8gdHIucHJvamVjdChMYXRMbmcuY29udmVydChvcHRpb25zLmNlbnRlcikpLnN1YihvZmZzZXQuZGl2KHNjYWxlKSkgOiBmcm9tLFxuICAgICAgICAgICAgYXJvdW5kO1xuXG4gICAgICAgIGlmICh6b29tICE9PSBzdGFydFpvb20pIHtcbiAgICAgICAgICAgIGFyb3VuZCA9IHRyLnBvaW50TG9jYXRpb24odHIuY2VudGVyUG9pbnQuYWRkKHRvLnN1Yihmcm9tKS5kaXYoMSAtIDEgLyBzY2FsZSkpKTtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XG5cbiAgICAgICAgdGhpcy5fZWFzZShmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgaWYgKHpvb20gIT09IHN0YXJ0Wm9vbSkge1xuICAgICAgICAgICAgICAgIHRyLnNldFpvb21Bcm91bmQoaW50ZXJwb2xhdGUoc3RhcnRab29tLCB6b29tLCBrKSwgYXJvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHIuY2VudGVyID0gdHIudW5wcm9qZWN0KGZyb20uYWRkKHRvLnN1Yihmcm9tKS5tdWx0KGspKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBpdGNoICE9PSBzdGFydFBpdGNoKSB7XG4gICAgICAgICAgICAgICAgdHIucGl0Y2ggPSBpbnRlcnBvbGF0ZShzdGFydFBpdGNoLCBwaXRjaCwgayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZmlyZSgnbW92ZScpO1xuICAgICAgICAgICAgaWYgKHRoaXMuem9vbWluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucm90YXRpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ3JvdGF0ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRoaXMuem9vbWluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yb3RhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlZW5kJyk7XG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGbHlpbmcgYW5pbWF0aW9uIHRvIGEgc3BlY2lmaWVkIGxvY2F0aW9uL3pvb20vYmVhcmluZyB3aXRoIGF1dG9tYXRpYyBjdXJ2ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtDYW1lcmFPcHRpb25zfSBvcHRpb25zIG1hcCB2aWV3IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc3BlZWQ9MS4yXSBIb3cgZmFzdCBhbmltYXRpb24gb2NjdXJzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmN1cnZlPTEuNDJdIEhvdyBtdWNoIHpvb21pbmcgb3V0IG9jY3VycyBkdXJpbmcgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZWFzaW5nXVxuICAgICAqIEBmaXJlcyBtb3Zlc3RhcnRcbiAgICAgKiBAZmlyZXMgbW92ZWVuZFxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gZmx5IHdpdGggZGVmYXVsdCBvcHRpb25zIHRvIG51bGwgaXNsYW5kXG4gICAgICogbWFwLmZseVRvKHtjZW50ZXI6IFswLCAwXSwgem9vbTogOX0pO1xuICAgICAqIC8vIHVzaW5nIGZseVRvIG9wdGlvbnNcbiAgICAgKiBtYXAuZmx5VG8oe1xuICAgICAqICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICogICB6b29tOiA5LFxuICAgICAqICAgc3BlZWQ6IDAuMixcbiAgICAgKiAgIGN1cnZlOiAxLFxuICAgICAqICAgZWFzaW5nOiBmdW5jdGlvbih0KSB7XG4gICAgICogICAgIHJldHVybiB0O1xuICAgICAqICAgfVxuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZseVRvOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc3RvcCgpO1xuXG4gICAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICAgICAgICBvZmZzZXQ6IFswLCAwXSxcbiAgICAgICAgICAgIHNwZWVkOiAxLjIsXG4gICAgICAgICAgICBjdXJ2ZTogMS40MixcbiAgICAgICAgICAgIGVhc2luZzogdXRpbC5lYXNlXG4gICAgICAgIH0sIG9wdGlvbnMpO1xuXG4gICAgICAgIHZhciB0ciA9IHRoaXMudHJhbnNmb3JtLFxuICAgICAgICAgICAgb2Zmc2V0ID0gUG9pbnQuY29udmVydChvcHRpb25zLm9mZnNldCksXG4gICAgICAgICAgICBzdGFydFpvb20gPSB0aGlzLmdldFpvb20oKSxcbiAgICAgICAgICAgIHN0YXJ0QmVhcmluZyA9IHRoaXMuZ2V0QmVhcmluZygpO1xuXG4gICAgICAgIHZhciBjZW50ZXIgPSAnY2VudGVyJyBpbiBvcHRpb25zID8gTGF0TG5nLmNvbnZlcnQob3B0aW9ucy5jZW50ZXIpIDogdGhpcy5nZXRDZW50ZXIoKTtcbiAgICAgICAgdmFyIHpvb20gPSAnem9vbScgaW4gb3B0aW9ucyA/ICArb3B0aW9ucy56b29tIDogc3RhcnRab29tO1xuICAgICAgICB2YXIgYmVhcmluZyA9ICdiZWFyaW5nJyBpbiBvcHRpb25zID8gdGhpcy5fbm9ybWFsaXplQmVhcmluZyhvcHRpb25zLmJlYXJpbmcsIHN0YXJ0QmVhcmluZykgOiBzdGFydEJlYXJpbmc7XG5cbiAgICAgICAgdmFyIHNjYWxlID0gdHIuem9vbVNjYWxlKHpvb20gLSBzdGFydFpvb20pLFxuICAgICAgICAgICAgZnJvbSA9IHRyLnBvaW50LFxuICAgICAgICAgICAgdG8gPSB0ci5wcm9qZWN0KGNlbnRlcikuc3ViKG9mZnNldC5kaXYoc2NhbGUpKTtcblxuICAgICAgICB2YXIgc3RhcnRXb3JsZFNpemUgPSB0ci53b3JsZFNpemUsXG4gICAgICAgICAgICByaG8gPSBvcHRpb25zLmN1cnZlLFxuICAgICAgICAgICAgViA9IG9wdGlvbnMuc3BlZWQsXG5cbiAgICAgICAgICAgIHcwID0gTWF0aC5tYXgodHIud2lkdGgsIHRyLmhlaWdodCksXG4gICAgICAgICAgICB3MSA9IHcwIC8gc2NhbGUsXG4gICAgICAgICAgICB1MSA9IHRvLnN1Yihmcm9tKS5tYWcoKSxcbiAgICAgICAgICAgIHJobzIgPSByaG8gKiByaG87XG5cbiAgICAgICAgZnVuY3Rpb24gcihpKSB7XG4gICAgICAgICAgICB2YXIgYiA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIChpID8gLTEgOiAxKSAqIHJobzIgKiByaG8yICogdTEgKiB1MSkgLyAoMiAqIChpID8gdzEgOiB3MCkgKiByaG8yICogdTEpO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubG9nKE1hdGguc3FydChiICogYiArIDEpIC0gYik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaW5oKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSAtIE1hdGguZXhwKC1uKSkgLyAyOyB9XG4gICAgICAgIGZ1bmN0aW9uIGNvc2gobikgeyByZXR1cm4gKE1hdGguZXhwKG4pICsgTWF0aC5leHAoLW4pKSAvIDI7IH1cbiAgICAgICAgZnVuY3Rpb24gdGFuaChuKSB7IHJldHVybiBzaW5oKG4pIC8gY29zaChuKTsgfVxuXG4gICAgICAgIHZhciByMCA9IHIoMCksXG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIChjb3NoKHIwKSAvIGNvc2gocjAgKyByaG8gKiBzKSk7IH0sXG4gICAgICAgICAgICB1ID0gZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHcwICogKChjb3NoKHIwKSAqIHRhbmgocjAgKyByaG8gKiBzKSAtIHNpbmgocjApKSAvIHJobzIpIC8gdTE7IH0sXG4gICAgICAgICAgICBTID0gKHIoMSkgLSByMCkgLyByaG87XG5cbiAgICAgICAgaWYgKE1hdGguYWJzKHUxKSA8IDAuMDAwMDAxKSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnModzAgLSB3MSkgPCAwLjAwMDAwMSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBrID0gdzEgPCB3MCA/IC0xIDogMTtcbiAgICAgICAgICAgIFMgPSBNYXRoLmFicyhNYXRoLmxvZyh3MSAvIHcwKSkgLyByaG87XG5cbiAgICAgICAgICAgIHUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4gICAgICAgICAgICB3ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gTWF0aC5leHAoayAqIHJobyAqIHMpOyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0aW9ucy5kdXJhdGlvbiA9IDEwMDAgKiBTIC8gVjtcblxuICAgICAgICB0aGlzLnpvb21pbmcgPSB0cnVlO1xuICAgICAgICBpZiAoc3RhcnRCZWFyaW5nICE9PSBiZWFyaW5nKSB0aGlzLnJvdGF0aW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xuXG4gICAgICAgIHRoaXMuX2Vhc2UoZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgIHZhciBzID0gayAqIFMsXG4gICAgICAgICAgICAgICAgdXMgPSB1KHMpO1xuXG4gICAgICAgICAgICB0ci56b29tID0gc3RhcnRab29tICsgdHIuc2NhbGVab29tKDEgLyB3KHMpKTtcbiAgICAgICAgICAgIHRyLmNlbnRlciA9IHRyLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWIoZnJvbSkubXVsdCh1cykpLCBzdGFydFdvcmxkU2l6ZSk7XG5cbiAgICAgICAgICAgIGlmIChiZWFyaW5nICE9PSBzdGFydEJlYXJpbmcpIHtcbiAgICAgICAgICAgICAgICB0ci5iZWFyaW5nID0gaW50ZXJwb2xhdGUoc3RhcnRCZWFyaW5nLCBiZWFyaW5nLCBrKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnem9vbScpO1xuICAgICAgICAgICAgaWYgKGJlYXJpbmcgIT09IHN0YXJ0QmVhcmluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgncm90YXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy56b29taW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgfSwgb3B0aW9ucyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGlzRWFzaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fYWJvcnRGbjtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU3RvcCBjdXJyZW50IGFuaW1hdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge3RoaXN9XG4gICAgICovXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9hYm9ydEZuKSB7XG4gICAgICAgICAgICB0aGlzLl9hYm9ydEZuLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fYWJvcnRGbjtcblxuICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9maW5pc2hGbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2Vhc2U6IGZ1bmN0aW9uKGZyYW1lLCBmaW5pc2gsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoRm4gPSBmaW5pc2g7XG4gICAgICAgIHRoaXMuX2Fib3J0Rm4gPSBicm93c2VyLnRpbWVkKGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICBmcmFtZS5jYWxsKHRoaXMsIG9wdGlvbnMuZWFzaW5nKHQpKTtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2Fib3J0Rm47XG4gICAgICAgICAgICAgICAgdGhpcy5fZmluaXNoRm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5fZmluaXNoRm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgPyAwIDogb3B0aW9ucy5kdXJhdGlvbiwgdGhpcyk7XG4gICAgfSxcblxuICAgIC8vIGNvbnZlcnQgYmVhcmluZyBzbyB0aGF0IGl0J3MgbnVtZXJpY2FsbHkgY2xvc2UgdG8gdGhlIGN1cnJlbnQgb25lIHNvIHRoYXQgaXQgaW50ZXJwb2xhdGVzIHByb3Blcmx5XG4gICAgX25vcm1hbGl6ZUJlYXJpbmc6IGZ1bmN0aW9uKGJlYXJpbmcsIGN1cnJlbnRCZWFyaW5nKSB7XG4gICAgICAgIGJlYXJpbmcgPSB1dGlsLndyYXAoYmVhcmluZywgLTE4MCwgMTgwKTtcbiAgICAgICAgdmFyIGRpZmYgPSBNYXRoLmFicyhiZWFyaW5nIC0gY3VycmVudEJlYXJpbmcpO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyAtIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgLT0gMzYwO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYmVhcmluZyArIDM2MCAtIGN1cnJlbnRCZWFyaW5nKSA8IGRpZmYpIGJlYXJpbmcgKz0gMzYwO1xuICAgICAgICByZXR1cm4gYmVhcmluZztcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUVhc2luZzogZnVuY3Rpb24oZHVyYXRpb24sIHpvb20sIGJlemllcikge1xuICAgICAgICB2YXIgZWFzaW5nO1xuXG4gICAgICAgIGlmICh0aGlzLmVhc2UpIHtcbiAgICAgICAgICAgIHZhciBlYXNlID0gdGhpcy5lYXNlLFxuICAgICAgICAgICAgICAgIHQgPSAoRGF0ZS5ub3coKSAtIGVhc2Uuc3RhcnQpIC8gZWFzZS5kdXJhdGlvbixcbiAgICAgICAgICAgICAgICBzcGVlZCA9IGVhc2UuZWFzaW5nKHQgKyAwLjAxKSAtIGVhc2UuZWFzaW5nKHQpLFxuXG4gICAgICAgICAgICAgICAgLy8gUXVpY2sgaGFjayB0byBtYWtlIG5ldyBiZXppZXIgdGhhdCBpcyBjb250aW51b3VzIHdpdGggbGFzdFxuICAgICAgICAgICAgICAgIHggPSAwLjI3IC8gTWF0aC5zcXJ0KHNwZWVkICogc3BlZWQgKyAwLjAwMDEpICogMC4wMSxcbiAgICAgICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KDAuMjcgKiAwLjI3IC0geCAqIHgpO1xuXG4gICAgICAgICAgICBlYXNpbmcgPSB1dGlsLmJlemllcih4LCB5LCAwLjI1LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyA9IGJlemllciA/IHV0aWwuYmV6aWVyLmFwcGx5KHV0aWwsIGJlemllcikgOiB1dGlsLmVhc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSBpbmZvcm1hdGlvbiBvbiBjdXJyZW50IGVhc2luZ1xuICAgICAgICB0aGlzLmVhc2UgPSB7XG4gICAgICAgICAgICBzdGFydDogKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcbiAgICAgICAgICAgIHRvOiBNYXRoLnBvdygyLCB6b29tKSxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgIGVhc2luZzogZWFzaW5nXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGVhc2luZztcbiAgICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBdHRyaWJ1dGlvbjtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2xcbiAqIEBjbGFzcyBBdHRyaWJ1dGlvblxuICogQGV4YW1wbGVcbiAqIG1hcC5hZGRDb250cm9sKG5ldyBtYXBib3hnbC5BdHRyaWJ1dGlvbigpKTtcbiAqL1xuZnVuY3Rpb24gQXR0cmlidXRpb24oKSB7fVxuXG5BdHRyaWJ1dGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICdib3R0b20tcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsLWF0dHJpYicsXG4gICAgICAgICAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBET00uY3JlYXRlKCdkaXYnLCBjbGFzc05hbWUsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmxvYWQnLCB0aGlzLl91cGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICAgIG1hcC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX3VwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgbWFwLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fdXBkYXRlLmJpbmQodGhpcykpO1xuICAgICAgICBtYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVFZGl0TGluay5iaW5kKHRoaXMpKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGF0dHJpYnV0aW9ucyA9IFtdO1xuXG4gICAgICAgIGlmICh0aGlzLl9tYXAuc3R5bGUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuX21hcC5zdHlsZS5zb3VyY2VzW2lkXTtcbiAgICAgICAgICAgICAgICBpZiAoc291cmNlLmF0dHJpYnV0aW9uICYmIGF0dHJpYnV0aW9ucy5pbmRleE9mKHNvdXJjZS5hdHRyaWJ1dGlvbikgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9ucy5wdXNoKHNvdXJjZS5hdHRyaWJ1dGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY29udGFpbmVyLmlubmVySFRNTCA9IGF0dHJpYnV0aW9ucy5qb2luKCcgfCAnKTtcbiAgICAgICAgdGhpcy5fZWRpdExpbmsgPSB0aGlzLl9jb250YWluZXIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbWFwYm94LWltcHJvdmUtbWFwJylbMF07XG4gICAgICAgIHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVFZGl0TGluazogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9lZGl0TGluaykge1xuICAgICAgICAgICAgdmFyIGNlbnRlciA9IHRoaXMuX21hcC5nZXRDZW50ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX2VkaXRMaW5rLmhyZWYgPSAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXAtZmVlZGJhY2svIy8nICtcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyLmxuZyArICcvJyArIGNlbnRlci5sYXQgKyAnLycgKyBNYXRoLnJvdW5kKHRoaXMuX21hcC5nZXRab29tKCkgKyAxKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbnRyb2w7XG5cbi8qKlxuICogQSBiYXNlIGNsYXNzIGZvciBtYXAtcmVsYXRlZCBpbnRlcmZhY2UgZWxlbWVudHMuXG4gKlxuICogQGNsYXNzIENvbnRyb2xcbiAqL1xuZnVuY3Rpb24gQ29udHJvbCgpIHt9XG5cbkNvbnRyb2wucHJvdG90eXBlID0ge1xuICAgIC8qKlxuICAgICAqIEFkZCB0aGlzIGNvbnRyb2wgdG8gdGhlIG1hcCwgcmV0dXJuaW5nIHRoZSBjb250cm9sIGl0c2VsZlxuICAgICAqIGZvciBjaGFpbmluZy4gVGhpcyB3aWxsIGluc2VydCB0aGUgY29udHJvbCdzIERPTSBlbGVtZW50IGludG9cbiAgICAgKiB0aGUgbWFwJ3MgRE9NIGVsZW1lbnQgaWYgdGhlIGNvbnRyb2wgaGFzIGEgYHBvc2l0aW9uYCBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbWFwXG4gICAgICogQHJldHVybnMge0NvbnRyb2x9IHRoaXNcbiAgICAgKi9cbiAgICBhZGRUbzogZnVuY3Rpb24obWFwKSB7XG4gICAgICAgIHRoaXMuX21hcCA9IG1hcDtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMucG9zaXRpb24pIHtcbiAgICAgICAgICAgIHZhciBwb3MgPSB0aGlzLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgICAgICB2YXIgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xuICAgICAgICAgICAgY29udGFpbmVyLmNsYXNzTmFtZSArPSAnIG1hcGJveGdsLWN0cmwnO1xuICAgICAgICAgICAgaWYgKHBvcy5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuaW5zZXJ0QmVmb3JlKGNvbnRhaW5lciwgY29ybmVyLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhpcyBjb250cm9sIGZyb20gdGhlIG1hcCBpdCBoYXMgYmVlbiBhZGRlZCB0by5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtDb250cm9sfSB0aGlzXG4gICAgICovXG4gICAgcmVtb3ZlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub25SZW1vdmUpIHRoaXMub25SZW1vdmUodGhpcy5fbWFwKTtcbiAgICAgICAgdGhpcy5fbWFwID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcbnZhciBET00gPSByZXF1aXJlKCcuLi8uLi91dGlsL2RvbScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBOYXZpZ2F0aW9uO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuYXZpZ2F0aW9uIGNvbnRyb2wgd2l0aCB6b29tIGJ1dHRvbnMgYW5kIGEgY29tcGFzc1xuICogQGNsYXNzIE5hdmlnYXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wb3NpdGlvbj10b3AtcmlnaHRdIEEgc3RyaW5nIGluZGljYXRpbmcgdGhlIGNvbnRyb2wncyBwb3NpdGlvbiBvbiB0aGUgbWFwLiBPcHRpb25zIGFyZSBgdG9wLXJpZ2h0YCwgYHRvcC1sZWZ0YCwgYGJvdHRvbS1yaWdodGAsIGBib3R0b20tbGVmdGBcbiAqIEBleGFtcGxlXG4gKiBtYXAuYWRkQ29udHJvbChuZXcgbWFwYm94Z2wuTmF2aWdhdGlvbih7cG9zaXRpb246ICd0b3AtbGVmdCd9KSk7IC8vIHBvc2l0aW9uIGlzIG9wdGlvbmFsXG4gKi9cbmZ1bmN0aW9uIE5hdmlnYXRpb24ob3B0aW9ucykge1xuICAgIHV0aWwuc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcbn1cblxuTmF2aWdhdGlvbi5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoQ29udHJvbCwge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgcG9zaXRpb246ICd0b3AtcmlnaHQnXG4gICAgfSxcblxuICAgIG9uQWRkOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9ICdtYXBib3hnbC1jdHJsJztcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgY2xhc3NOYW1lICsgJy1ncm91cCcsIG1hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgdGhpcy5fem9vbUluQnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLWluJywgbWFwLnpvb21Jbi5iaW5kKG1hcCkpO1xuICAgICAgICB0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKGNsYXNzTmFtZSArICctaWNvbiAnICsgY2xhc3NOYW1lICsgJy16b29tLW91dCcsIG1hcC56b29tT3V0LmJpbmQobWFwKSk7XG4gICAgICAgIHRoaXMuX2NvbXBhc3MgPSB0aGlzLl9jcmVhdGVCdXR0b24oY2xhc3NOYW1lICsgJy1jb21wYXNzJywgbWFwLnJlc2V0Tm9ydGguYmluZChtYXApKTtcblxuICAgICAgICB2YXIgY29tcGFzc0NhbnZhcyA9IHRoaXMuX2NvbXBhc3NDYW52YXMgPSBET00uY3JlYXRlKCdjYW52YXMnLCBjbGFzc05hbWUgKyAnLWNvbXBhc3MtY2FudmFzJywgdGhpcy5fY29tcGFzcyk7XG4gICAgICAgIGNvbXBhc3NDYW52YXMuc3R5bGUuY3NzVGV4dCA9ICd3aWR0aDozMHB4OyBoZWlnaHQ6MzBweDsnO1xuICAgICAgICBjb21wYXNzQ2FudmFzLndpZHRoID0gMjYgKiAyO1xuICAgICAgICBjb21wYXNzQ2FudmFzLmhlaWdodCA9IDI2ICogMjtcblxuICAgICAgICB0aGlzLl9jb21wYXNzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uQ29tcGFzc0Rvd24uYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc01vdmUgPSB0aGlzLl9vbkNvbXBhc3NNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX29uQ29tcGFzc1VwID0gdGhpcy5fb25Db21wYXNzVXAuYmluZCh0aGlzKTtcblxuICAgICAgICB0aGlzLl9jb21wYXNzQ3R4ID0gY29tcGFzc0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgIG1hcC5vbigncm90YXRlJywgdGhpcy5fZHJhd05vcnRoLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLl9kcmF3Tm9ydGgoKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH0sXG5cbiAgICBfb25Db21wYXNzRG93bjogZnVuY3Rpb24oZSkge1xuICAgICAgICBET00uZGlzYWJsZURyYWcoKTtcblxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkNvbXBhc3NNb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQ29tcGFzc1VwKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG5cbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgX29uQ29tcGFzc01vdmU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLnNjcmVlblgsXG4gICAgICAgICAgICBkID0geCA8IDIgPyAtNSA6IC8vIGxlZnQgZWRnZSBvZiB0aGUgc2NyZWVuLCBjb250aW51ZSByb3RhdGluZ1xuICAgICAgICAgICAgICAgIHggPiB3aW5kb3cuc2NyZWVuLndpZHRoIC0gMiA/IDUgOiAvLyByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgKHggLSB0aGlzLl9wcmV2WCkgLyA0O1xuXG4gICAgICAgIHRoaXMuX21hcC5zZXRCZWFyaW5nKHRoaXMuX21hcC5nZXRCZWFyaW5nKCkgLSBkKTtcbiAgICAgICAgdGhpcy5fcHJldlggPSBlLnNjcmVlblg7XG4gICAgICAgIHRoaXMuX21vdmVkID0gdHJ1ZTtcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSxcblxuICAgIF9vbkNvbXBhc3NVcDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQ29tcGFzc01vdmUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Db21wYXNzVXApO1xuICAgICAgICBET00uZW5hYmxlRHJhZygpO1xuXG4gICAgICAgIGlmICh0aGlzLl9tb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy5fbW92ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIERPTS5zdXBwcmVzc0NsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24oY2xhc3NOYW1lLCBmbikge1xuICAgICAgICB2YXIgYSA9IERPTS5jcmVhdGUoJ2J1dHRvbicsIGNsYXNzTmFtZSwgdGhpcy5fY29udGFpbmVyKTtcbiAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkgeyBmbigpOyB9KTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfSxcblxuICAgIF9kcmF3Tm9ydGg6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmFkID0gMjAsXG4gICAgICAgICAgICB3aWR0aCA9IDgsXG4gICAgICAgICAgICBjZW50ZXIgPSAyNixcbiAgICAgICAgICAgIGFuZ2xlID0gdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSArIChNYXRoLlBJIC8gMiksXG4gICAgICAgICAgICBjdHggPSB0aGlzLl9jb21wYXNzQ3R4O1xuXG4gICAgICAgIHRoaXMuX2NvbXBhc3NDYW52YXMud2lkdGggPSB0aGlzLl9jb21wYXNzQ2FudmFzLndpZHRoO1xuXG4gICAgICAgIGN0eC50cmFuc2xhdGUoY2VudGVyLCBjZW50ZXIpO1xuICAgICAgICBjdHgucm90YXRlKGFuZ2xlKTtcblxuICAgICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSAnIzAwMCc7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgLXdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbygtcmFkLCAwKTtcbiAgICAgICAgY3R4LmxpbmVUbygwLCB3aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gJyNiYmInO1xuICAgICAgICBjdHgubW92ZVRvKDAsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIHdpZHRoKTtcbiAgICAgICAgY3R4LmxpbmVUbyhyYWQsIDApO1xuICAgICAgICBjdHgubGluZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5maWxsKCk7XG5cbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSAnI2ZmZic7XG4gICAgICAgIGN0eC5saW5lV2lkdGggPSA0O1xuICAgICAgICBjdHgubW92ZVRvKDAsIC13aWR0aCk7XG4gICAgICAgIGN0eC5saW5lVG8oMCwgd2lkdGgpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBJbnRlcmFjdGlvbiA9IHJlcXVpcmUoJy4vaW50ZXJhY3Rpb24nKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvdXRpbCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nQm91bmRzID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmdfYm91bmRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gSGFuZGxlcnM7XG5cbmZ1bmN0aW9uIEhhbmRsZXJzKG1hcCkge1xuXG4gICAgdmFyIHJvdGF0ZUVuZDtcblxuICAgIHZhciBib3g7XG5cbiAgICB2YXIgaW5lcnRpYUxpbmVhcml0eSA9IDAuMixcbiAgICAgICAgaW5lcnRpYUVhc2luZyA9IHV0aWwuYmV6aWVyKDAsIDAsIGluZXJ0aWFMaW5lYXJpdHksIDEpO1xuXG4gICAgZnVuY3Rpb24gYm94em9vbUZpbmlzaCgpIHtcbiAgICAgICAgaWYgKGJveCkge1xuICAgICAgICAgICAgYm94LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoYm94KTtcbiAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgIGJveCA9IGZhbHNlO1xuICAgICAgICAgICAgRE9NLmVuYWJsZURyYWcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaW50ZXJhY3Rpb24gPSBuZXcgSW50ZXJhY3Rpb24obWFwLmdldENhbnZhcygpKVxuICAgICAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5sYXRMbmcgPSBtYXAudW5wcm9qZWN0KGUucG9pbnQpO1xuICAgICAgICAgICAgbWFwLmZpcmUoJ2NsaWNrJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZGJsY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnZGJsY2xpY2snLCBlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBlLmxhdExuZyA9IG1hcC51bnByb2plY3QoZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW91c2Vtb3ZlJywgZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVzdGFydCcpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbWFwLnN0b3AoKTtcbiAgICAgICAgICAgIG1hcC5yZXNpemUoKTtcbiAgICAgICAgICAgIG1hcC51cGRhdGUoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYgKGUuYWx0S2V5IHx8IGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHBhbiA9IDgwO1xuICAgICAgICAgICAgdmFyIHJvdGF0ZSA9IDI7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHpvb21CeSh6KSB7XG4gICAgICAgICAgICAgICAgbWFwLnpvb21UbyhNYXRoLnJvdW5kKG1hcC5nZXRab29tKCkpICsgKGUuc2hpZnRLZXkgPyAyIDogMSkgKiB6KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFuQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5wYW5CeSh2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcm90YXRlQnkodikge1xuICAgICAgICAgICAgICAgIG1hcC5zZXRCZWFyaW5nKG1hcC5nZXRCZWFyaW5nKCkgKyB2KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDYxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTA3OlxuICAgICAgICAgICAgICAgIGNhc2UgMTcxOlxuICAgICAgICAgICAgICAgIGNhc2UgMTg3OlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTg5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTA5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTczOlxuICAgICAgICAgICAgICAgICAgICB6b29tQnkoLTEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM3OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQnkoLXJvdGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5CeShbLXBhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzk6XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVCeShyb3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFuQnkoW3BhbiwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzg6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCAtcGFuXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDA6XG4gICAgICAgICAgICAgICAgICAgIHBhbkJ5KFswLCBwYW5dKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIG1hcC5zdG9wKCk7XG4gICAgICAgICAgICB2YXIgbW91c2VMb2NhdGlvbiA9IG1hcC50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihlLnBvaW50LmFkZChlLm9mZnNldCkpO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5zZXRMb2NhdGlvbkF0UG9pbnQobW91c2VMb2NhdGlvbiwgZS5wb2ludCk7XG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3BhbmVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5pbmVydGlhKSB7XG4gICAgICAgICAgICAgICAgbWFwLmZpcmUoJ21vdmVlbmQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29udmVydCB2ZWxvY2l0eSB0byBweC9zICYgYWRqdXN0IGZvciBpbmNyZWFzZWQgaW5pdGlhbCBhbmltYXRpb24gc3BlZWQgd2hlbiBlYXNpbmcgb3V0XG4gICAgICAgICAgICAgICAgdmFyIHZlbG9jaXR5ID0gZS5pbmVydGlhLm11bHQoMTAwMCAqIGluZXJ0aWFMaW5lYXJpdHkpLFxuICAgICAgICAgICAgICAgICAgICBzcGVlZCA9IHZlbG9jaXR5Lm1hZygpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heFNwZWVkID0gNDAwMDsgLy8gcHgvc1xuXG4gICAgICAgICAgICAgICAgaWYgKHNwZWVkID49IG1heFNwZWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwZWVkID0gbWF4U3BlZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZlbG9jaXR5Ll91bml0KCkuX211bHQobWF4U3BlZWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBkZWNlbGVyYXRpb24gPSA4MDAwLCAvLyBweC9zXjJcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBzcGVlZCAvIChkZWNlbGVyYXRpb24gKiBpbmVydGlhTGluZWFyaXR5KSxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gdmVsb2NpdHkubXVsdCgtZHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG4gICAgICAgICAgICAgICAgbWFwLnBhbkJ5KG9mZnNldCwge1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24gKiAxMDAwLFxuICAgICAgICAgICAgICAgICAgICBlYXNpbmc6IGluZXJ0aWFFYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIG5vTW92ZVN0YXJ0OiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignem9vbScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIFNjYWxlIGJ5IHNpZ21vaWQgb2Ygc2Nyb2xsIHdoZWVsIGRlbHRhLlxuICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAvICgxICsgTWF0aC5leHAoLU1hdGguYWJzKGUuZGVsdGEgLyAxMDApKSk7XG4gICAgICAgICAgICBpZiAoZS5kZWx0YSA8IDAgJiYgc2NhbGUgIT09IDApIHNjYWxlID0gMSAvIHNjYWxlO1xuXG4gICAgICAgICAgICB2YXIgZnJvbVNjYWxlID0gbWFwLmVhc2UgJiYgaXNGaW5pdGUoZS5kZWx0YSkgPyBtYXAuZWFzZS50byA6IG1hcC50cmFuc2Zvcm0uc2NhbGUsXG4gICAgICAgICAgICAgICAgZHVyYXRpb24gPSAhaXNGaW5pdGUoZS5kZWx0YSkgPyA4MDAgOiAwO1xuXG4gICAgICAgICAgICBtYXAuem9vbVRvKG1hcC50cmFuc2Zvcm0uc2NhbGVab29tKGZyb21TY2FsZSAqIHNjYWxlKSwge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICBhcm91bmQ6IG1hcC51bnByb2plY3QoZS5wb2ludClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ3JvdGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIHZhciBjZW50ZXIgPSBtYXAudHJhbnNmb3JtLmNlbnRlclBvaW50LCAvLyBDZW50ZXIgb2Ygcm90YXRpb25cbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyID0gZS5zdGFydC5zdWIoY2VudGVyKSxcbiAgICAgICAgICAgICAgICBzdGFydFRvQ2VudGVyRGlzdCA9IHN0YXJ0VG9DZW50ZXIubWFnKCk7XG5cbiAgICAgICAgICAgIG1hcC5yb3RhdGluZyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBjbGljayB3YXMgdG9vIGNsb3NlIHRvIHRoZSBjZW50ZXIsIG1vdmUgdGhlIGNlbnRlciBvZiByb3RhdGlvbiBieSAyMDAgcGl4ZWxzXG4gICAgICAgICAgICAvLyBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBjbGljay5cbiAgICAgICAgICAgIGlmIChzdGFydFRvQ2VudGVyRGlzdCA8IDIwMCkge1xuICAgICAgICAgICAgICAgIGNlbnRlciA9IGUuc3RhcnQuYWRkKG5ldyBQb2ludCgtMjAwLCAwKS5fcm90YXRlKHN0YXJ0VG9DZW50ZXIuYW5nbGUoKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYmVhcmluZ0RpZmYgPSBlLnByZXYuc3ViKGNlbnRlcikuYW5nbGVXaXRoKGUuY3VycmVudC5zdWIoY2VudGVyKSkgLyBNYXRoLlBJICogMTgwO1xuICAgICAgICAgICAgbWFwLnRyYW5zZm9ybS5iZWFyaW5nID0gbWFwLmdldEJlYXJpbmcoKSAtIGJlYXJpbmdEaWZmO1xuXG4gICAgICAgICAgICBtYXAuZmlyZSgnbW92ZScpLmZpcmUoJ3JvdGF0ZScpO1xuXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHJvdGF0ZUVuZCk7XG4gICAgICAgICAgICByb3RhdGVFbmQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBtYXAucm90YXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBtYXAuX3JlcmVuZGVyKCk7XG4gICAgICAgICAgICB9LCAyMDApO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2JveHpvb21zdGFydCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmICghYm94KSB7XG4gICAgICAgICAgICAgICAgYm94ID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWJveHpvb20nLCBtYXAuZ2V0Q29udGFpbmVyKCkpO1xuICAgICAgICAgICAgICAgIG1hcC5nZXRDb250YWluZXIoKS5jbGFzc0xpc3QuYWRkKCdtYXBib3hnbC1jcm9zc2hhaXInKTtcbiAgICAgICAgICAgICAgICBtYXAuZmlyZSgnYm94em9vbXN0YXJ0Jyk7XG4gICAgICAgICAgICAgICAgRE9NLmRpc2FibGVEcmFnKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBtaW5YID0gTWF0aC5taW4oZS5zdGFydC54LCBlLmN1cnJlbnQueCk7XG4gICAgICAgICAgICB2YXIgbWF4WCA9IE1hdGgubWF4KGUuc3RhcnQueCwgZS5jdXJyZW50LngpO1xuICAgICAgICAgICAgdmFyIG1pblkgPSBNYXRoLm1pbihlLnN0YXJ0LnksIGUuY3VycmVudC55KTtcbiAgICAgICAgICAgIHZhciBtYXhZID0gTWF0aC5tYXgoZS5zdGFydC55LCBlLmN1cnJlbnQueSk7XG5cbiAgICAgICAgICAgIERPTS5zZXRUcmFuc2Zvcm0oYm94LCAndHJhbnNsYXRlKCcgKyBtaW5YICsgJ3B4LCcgKyBtaW5ZICsgJ3B4KScpO1xuICAgICAgICAgICAgYm94LnN0eWxlLndpZHRoID0gKG1heFggLSBtaW5YKSArICdweCc7XG4gICAgICAgICAgICBib3guc3R5bGUuaGVpZ2h0ID0gKG1heFkgLSBtaW5ZKSArICdweCc7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWVuZCcsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGJveHpvb21GaW5pc2goKTtcblxuICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICAgICAgbWFwLnVucHJvamVjdChlLnN0YXJ0KSxcbiAgICAgICAgICAgICAgICBtYXAudW5wcm9qZWN0KGUuY3VycmVudClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzLCB7IGxpbmVhcjogdHJ1ZSB9KS5maXJlKCdib3h6b29tZW5kJywge1xuICAgICAgICAgICAgICAgIGJveFpvb21Cb3VuZHM6IGJvdW5kc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignYm94em9vbWNhbmNlbCcsIGJveHpvb21GaW5pc2gpO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogQWRkcyBwb3NpdGlvbmFsIGNvb3JkaW5hdGVzIHRvIFVSTCBoYXNoZXMuIFBhc3NlZCBhcyBhbiBvcHRpb24gdG8gdGhlIG1hcCBvYmplY3RcbiAqXG4gKiBAY2xhc3MgbWFwYm94Z2wuSGFzaFxuICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEhhc2g7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG5cbmZ1bmN0aW9uIEhhc2goKSB7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ19vbkhhc2hDaGFuZ2UnLFxuICAgICAgICAnX3VwZGF0ZUhhc2gnXG4gICAgXSwgdGhpcyk7XG59XG5cbkhhc2gucHJvdG90eXBlID0ge1xuICAgIC8qIE1hcCBlbGVtZW50IHRvIGxpc3RlbiBmb3IgY29vcmRpbmF0ZSBjaGFuZ2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwXG4gICAgICogQHJldHVybnMge0hhc2h9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmVlbmQnLCB0aGlzLl91cGRhdGVIYXNoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qIFJlbW92ZXMgaGFzaFxuICAgICAqXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICByZW1vdmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHRoaXMuX29uSGFzaENoYW5nZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlZW5kJywgdGhpcy5fdXBkYXRlSGFzaCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9tYXA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25IYXNoQ2hhbmdlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGxvYyA9IGxvY2F0aW9uLmhhc2gucmVwbGFjZSgnIycsICcnKS5zcGxpdCgnLycpO1xuICAgICAgICBpZiAobG9jLmxlbmd0aCA+PSAzKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAuanVtcFRvKHtcbiAgICAgICAgICAgICAgICBjZW50ZXI6IFsrbG9jWzFdLCArbG9jWzJdXSxcbiAgICAgICAgICAgICAgICB6b29tOiArbG9jWzBdLFxuICAgICAgICAgICAgICAgIGJlYXJpbmc6ICsobG9jWzNdIHx8IDApXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUhhc2g6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY2VudGVyID0gdGhpcy5fbWFwLmdldENlbnRlcigpLFxuICAgICAgICAgICAgem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCksXG4gICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5fbWFwLmdldEJlYXJpbmcoKSxcbiAgICAgICAgICAgIHByZWNpc2lvbiA9IE1hdGgubWF4KDAsIE1hdGguY2VpbChNYXRoLmxvZyh6b29tKSAvIE1hdGguTE4yKSksXG5cbiAgICAgICAgICAgIGhhc2ggPSAnIycgKyAoTWF0aC5yb3VuZCh6b29tICogMTAwKSAvIDEwMCkgK1xuICAgICAgICAgICAgICAgICcvJyArIGNlbnRlci5sYXQudG9GaXhlZChwcmVjaXNpb24pICtcbiAgICAgICAgICAgICAgICAnLycgKyBjZW50ZXIubG5nLnRvRml4ZWQocHJlY2lzaW9uKSArXG4gICAgICAgICAgICAgICAgKGJlYXJpbmcgPyAnLycgKyAoTWF0aC5yb3VuZChiZWFyaW5nICogMTApIC8gMTApIDogJycpO1xuXG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSgnJywgJycsIGhhc2gpO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudGVkID0gcmVxdWlyZSgnLi4vdXRpbC9ldmVudGVkJyk7XG52YXIgYnJvd3NlciA9IHJlcXVpcmUoJy4uL3V0aWwvYnJvd3NlcicpO1xudmFyIFBvaW50ID0gcmVxdWlyZSgncG9pbnQtZ2VvbWV0cnknKTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcmFjdGlvbjtcblxuLyoqXG4gKiBNb3VzZSBldmVudFxuICpcbiAqIEBldmVudCBNYXAjbW91c2Vtb3ZlXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtFdmVudH0gb3JpZ2luYWxFdmVudCB0aGUgb3JpZ2luYWwgRE9NIGV2ZW50XG4gKi9cblxuLyoqXG4gKiBEb3VibGUgY2xpY2sgZXZlbnQuXG4gKlxuICogQGV2ZW50IE1hcCNkYmxjbGlja1xuICogQHR5cGUge09iamVjdH1cbiAqIEBwcm9wZXJ0eSB7UG9pbnR9IHBvaW50IHRoZSBwaXhlbCBsb2NhdGlvbiBvZiB0aGUgZXZlbnRcbiAqL1xuXG4vKipcbiAqIFBhbiBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtQb2ludH0gcG9pbnQgdGhlIHBpeGVsIGxvY2F0aW9uIG9mIHRoZSBldmVudFxuICogQHByb3BlcnR5IHtQb2ludH0gb2Zmc2V0IGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBtb3ZlbWVudCBmcm9tIHRoZSBwcmV2aW91cyBtYXAgbG9jYXRpb24gdG8gdGhlIGN1cnJlbnQgb25lLlxuICovXG5cbi8qKlxuICogUGFuIGVuZCBldmVudFxuICpcbiAqIEBldmVudCBNYXAjcGFuZW5kXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlbG9jaXR5IGEgbWVhc3VyZSBvZiBob3cgbXVjaCBpbmVydGlhIHdhcyByZWNvcmRlZCBpbiB0aGlzIHBhbiBtb3Rpb25cbiAqL1xuXG5mdW5jdGlvbiBJbnRlcmFjdGlvbihlbCkge1xuICAgIHZhciBpbnRlcmFjdGlvbiA9IHRoaXM7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuXG4gICAgdmFyIHJvdGF0aW5nID0gZmFsc2UsXG4gICAgICAgIHBhbm5lZCA9IGZhbHNlLFxuICAgICAgICBib3h6b29tID0gZmFsc2UsXG4gICAgICAgIGZpcnN0UG9zID0gbnVsbCxcbiAgICAgICAgcG9zID0gbnVsbCxcbiAgICAgICAgaW5lcnRpYSA9IG51bGwsXG4gICAgICAgIG5vdztcblxuICAgIGZ1bmN0aW9uIG1vdXNlUG9zKGUpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChcbiAgICAgICAgICAgIGUuY2xpZW50WCAtIHJlY3QubGVmdCAtIGVsLmNsaWVudExlZnQsXG4gICAgICAgICAgICBlLmNsaWVudFkgLSByZWN0LnRvcCAtIGVsLmNsaWVudFRvcCk7XG4gICAgfVxuXG4gICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbihldikge1xuICAgICAgICByb3RhdGluZyA9IHRydWU7XG4gICAgICAgIGZpcnN0UG9zID0gcG9zID0gbW91c2VQb3MoZXYpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93biwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbm1vdXNldXAsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbm1vdXNlbW92ZSwgZmFsc2UpO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25jbGljaywgZmFsc2UpO1xuICAgIHNjcm9sbHdoZWVsKHpvb20pO1xuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kb3VibGVjbGljaywgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUsIGZhbHNlKTtcbiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywga2V5ZG93biwgZmFsc2UpO1xuXG4gICAgZnVuY3Rpb24gem9vbSh0eXBlLCBkZWx0YSwgcG9pbnQpIHtcbiAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnem9vbScsIHtcbiAgICAgICAgICAgIHNvdXJjZTogdHlwZSxcbiAgICAgICAgICAgIGRlbHRhOiBkZWx0YSxcbiAgICAgICAgICAgIHBvaW50OiBwb2ludFxuICAgICAgICB9KTtcbiAgICAgICAgaW5lcnRpYSA9IG51bGw7XG4gICAgICAgIG5vdyA9IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2NsaWNrJywge3BvaW50OiBwb2ludCwgb3JpZ2luYWxFdmVudDogZXZ9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3VzZW1vdmUocG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ21vdXNlbW92ZScsIHtwb2ludDogcG9pbnQsIG9yaWdpbmFsRXZlbnQ6IGV2fSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFuKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBwb3Muc3ViKHBvaW50KTtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3BhbicsIHtvZmZzZXQ6IG9mZnNldCwgcG9pbnQ6IHBvaW50fSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCBhbiBhdmVyYWdlZCB2ZXJzaW9uIG9mIHRoaXMgbW92ZW1lbnQgdG8gdGhlIGluZXJ0aWEgdmVjdG9yXG4gICAgICAgICAgICBpZiAoaW5lcnRpYSkge1xuICAgICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBub3c7XG4gICAgICAgICAgICAgICAgLy8gc29tZXRpbWVzIGl0J3MgMCBhZnRlciBzb21lIGVycmF0aWMgcGFuaW5nXG4gICAgICAgICAgICAgICAgaWYgKGR1cmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lID0gZHVyYXRpb24gKyBub3c7XG4gICAgICAgICAgICAgICAgICAgIGluZXJ0aWEucHVzaChbdGltZSwgcG9pbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGluZXJ0aWEubGVuZ3RoID4gMiAmJiB0aW1lIC0gaW5lcnRpYVswXVswXSA+IDEwMCkgaW5lcnRpYS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmVydGlhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgcG9zID0gcG9pbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemUoKSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3Jlc2l6ZScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtleWRvd24oZXYpIHtcbiAgICAgICAgaWYgKGJveHpvb20gJiYgZXYua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21jYW5jZWwnKTtcbiAgICAgICAgICAgIGJveHpvb20gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2tleWRvd24nLCBldik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcm90YXRlKHBvaW50KSB7XG4gICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ3JvdGF0ZScsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogZmlyc3RQb3MsXG4gICAgICAgICAgICAgICAgcHJldjogcG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IHBvaW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvcyA9IHBvaW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG91YmxlY2xpY2socG9pbnQsIGV2KSB7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2RibGNsaWNrJywge1xuICAgICAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZWRvd24oZXYpIHtcbiAgICAgICAgZmlyc3RQb3MgPSBwb3MgPSBtb3VzZVBvcyhldik7XG4gICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2Rvd24nKTtcbiAgICAgICAgaWYgKGV2LnNoaWZ0S2V5IHx8ICgoZXYud2hpY2ggPT09IDEpICYmIChldi5idXR0b24gPT09IDEpKSkge1xuICAgICAgICAgIGJveHpvb20gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25tb3VzZXVwKGV2KSB7XG4gICAgICAgIHBhbm5lZCA9IHBvcyAmJiBmaXJzdFBvcyAmJiAocG9zLnggIT09IGZpcnN0UG9zLnggfHwgcG9zLnkgIT09IGZpcnN0UG9zLnkpO1xuXG4gICAgICAgIHJvdGF0aW5nID0gZmFsc2U7XG4gICAgICAgIHBvcyA9IG51bGw7XG5cbiAgICAgICAgaWYgKGJveHpvb20pIHtcbiAgICAgICAgICAgIGludGVyYWN0aW9uLmZpcmUoJ2JveHpvb21lbmQnLCB7XG4gICAgICAgICAgICAgICAgc3RhcnQ6IGZpcnN0UG9zLFxuICAgICAgICAgICAgICAgIGN1cnJlbnQ6IG1vdXNlUG9zKGV2KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBib3h6b29tID0gZmFsc2U7XG5cbiAgICAgICAgfSBlbHNlIGlmIChpbmVydGlhICYmIGluZXJ0aWEubGVuZ3RoID49IDIgJiYgbm93ID4gRGF0ZS5ub3coKSAtIDEwMCkge1xuICAgICAgICAgICAgdmFyIGxhc3QgPSBpbmVydGlhW2luZXJ0aWEubGVuZ3RoIC0gMV0sXG4gICAgICAgICAgICAgICAgZmlyc3QgPSBpbmVydGlhWzBdLFxuICAgICAgICAgICAgICAgIHZlbG9jaXR5ID0gbGFzdFsxXS5zdWIoZmlyc3RbMV0pLmRpdihsYXN0WzBdIC0gZmlyc3RbMF0pO1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgncGFuZW5kJywge2luZXJ0aWE6IHZlbG9jaXR5fSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChwb3MpIHtcbiAgICAgICAgICBpbnRlcmFjdGlvbi5maXJlKCdwYW5lbmQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluZXJ0aWEgPSBudWxsO1xuICAgICAgICBub3cgPSBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubW91c2Vtb3ZlKGV2KSB7XG4gICAgICAgIHZhciBwb2ludCA9IG1vdXNlUG9zKGV2KTtcblxuICAgICAgICBpZiAoYm94em9vbSkge1xuICAgICAgICAgICAgaW50ZXJhY3Rpb24uZmlyZSgnYm94em9vbXN0YXJ0Jywge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBmaXJzdFBvcyxcbiAgICAgICAgICAgICAgICBjdXJyZW50OiBwb2ludFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIGlmIChyb3RhdGluZykge1xuICAgICAgICAgICAgcm90YXRlKHBvaW50KTtcblxuICAgICAgICB9IGVsc2UgaWYgKHBvcykge1xuICAgICAgICAgICAgcGFuKHBvaW50KTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhcmdldCA9IGV2LnRvRWxlbWVudCB8fCBldi50YXJnZXQ7XG4gICAgICAgICAgICB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldCAhPT0gZWwgJiYgdGFyZ2V0LnBhcmVudE5vZGUpIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICBtb3VzZW1vdmUocG9pbnQsIGV2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uY2xpY2soZXYpIHtcbiAgICAgICAgaWYgKCFwYW5uZWQpIGNsaWNrKG1vdXNlUG9zKGV2KSwgZXYpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uZG91YmxlY2xpY2soZXYpIHtcbiAgICAgICAgZG91YmxlY2xpY2sobW91c2VQb3MoZXYpLCBldik7XG4gICAgICAgIHpvb20oJ3doZWVsJywgSW5maW5pdHkgKiAoZXYuc2hpZnRLZXkgPyAtMSA6IDEpLCBtb3VzZVBvcyhldikpO1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbHdoZWVsKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmaXJlZm94ID0gL0ZpcmVmb3gvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgc2FmYXJpID0gL1NhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIS9DaHJvbShpdW18ZSkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICB2YXIgdGltZSA9IHdpbmRvdy5wZXJmb3JtYW5jZSB8fCBEYXRlO1xuXG4gICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgd2hlZWwsIGZhbHNlKTtcbiAgICAgICAgZWwuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V3aGVlbCcsIG1vdXNld2hlZWwsIGZhbHNlKTtcblxuICAgICAgICB2YXIgbGFzdEV2ZW50ID0gMDtcblxuICAgICAgICB2YXIgdHlwZSA9IG51bGw7XG4gICAgICAgIHZhciB0eXBlVGltZW91dCA9IG51bGw7XG4gICAgICAgIHZhciBpbml0aWFsVmFsdWUgPSBudWxsO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNjcm9sbCh2YWx1ZSwgZXYpIHtcbiAgICAgICAgICAgIHZhciBzdGFtcCA9IHRpbWUubm93KCk7XG4gICAgICAgICAgICB2YXIgdGltZURlbHRhID0gc3RhbXAgLSBsYXN0RXZlbnQ7XG4gICAgICAgICAgICBsYXN0RXZlbnQgPSBzdGFtcDtcblxuICAgICAgICAgICAgdmFyIHBvaW50ID0gbW91c2VQb3MoZXYpO1xuXG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IDAgJiYgKHZhbHVlICUgNC4wMDAyNDQxNDA2MjUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIG1vdXNlIHdoZWVsIGV2ZW50LlxuICAgICAgICAgICAgICAgIHR5cGUgPSAnd2hlZWwnO1xuICAgICAgICAgICAgICAgIC8vIE5vcm1hbGl6ZSB0aGlzIHZhbHVlIHRvIG1hdGNoIHRyYWNrcGFkLlxuICAgICAgICAgICAgICAgIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSAvIDQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSAhPT0gMCAmJiBNYXRoLmFicyh2YWx1ZSkgPCA0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvbmUgaXMgZGVmaW5pdGVseSBhIHRyYWNrcGFkIGV2ZW50IGJlY2F1c2UgaXQgaXMgc28gc21hbGwuXG4gICAgICAgICAgICAgICAgdHlwZSA9ICd0cmFja3BhZCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRpbWVEZWx0YSA+IDQwMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgbGlrZWx5IGEgbmV3IHNjcm9sbCBhY3Rpb24uXG4gICAgICAgICAgICAgICAgdHlwZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgLy8gU3RhcnQgYSB0aW1lb3V0IGluIGNhc2UgdGhpcyB3YXMgYSBzaW5ndWxhciBldmVudCwgYW5kIGRlbHkgaXRcbiAgICAgICAgICAgICAgICAvLyBieSB1cCB0byA0MG1zLlxuICAgICAgICAgICAgICAgIHR5cGVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICd3aGVlbCc7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHR5cGUsIC1pbml0aWFsVmFsdWUsIHBvaW50KTtcbiAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVwZWF0aW5nIGV2ZW50LCBidXQgd2UgZG9uJ3Qga25vdyB0aGUgdHlwZSBvZiBldmVudFxuICAgICAgICAgICAgICAgIC8vIGp1c3QgeWV0LiBJZiB0aGUgZGVsdGEgcGVyIHRpbWUgaXMgc21hbGwsIHdlIGFzc3VtZSBpdCdzIGFcbiAgICAgICAgICAgICAgICAvLyBmYXN0IHRyYWNrcGFkOyBvdGhlcndpc2Ugd2Ugc3dpdGNoIGludG8gd2hlZWwgbW9kZS5cbiAgICAgICAgICAgICAgICB0eXBlID0gKE1hdGguYWJzKHRpbWVEZWx0YSAqIHZhbHVlKSA8IDIwMCkgPyAndHJhY2twYWQnIDogJ3doZWVsJztcblxuICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgZGVsYXllZCBldmVudCBpc24ndCBmaXJlZCBhZ2FpbiwgYmVjYXVzZSB3ZVxuICAgICAgICAgICAgICAgIC8vIGFjY3VtdWxhdGUgdGhlIHByZXZpb3VzIGV2ZW50ICh3aGljaCB3YXMgbGVzcyB0aGFuIDQwbXMgYWdvKSBpbnRvXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBldmVudC5cbiAgICAgICAgICAgICAgICBpZiAodHlwZVRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHR5cGVUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZVRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBpbml0aWFsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTbG93IGRvd24gem9vbSBpZiBzaGlmdCBrZXkgaXMgaGVsZCBmb3IgbW9yZSBwcmVjaXNlIHpvb21pbmdcbiAgICAgICAgICAgIGlmIChldi5zaGlmdEtleSAmJiB2YWx1ZSkgdmFsdWUgPSB2YWx1ZSAvIDQ7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZmlyZSB0aGUgY2FsbGJhY2sgaWYgd2UgYWN0dWFsbHkga25vdyB3aGF0IHR5cGUgb2Ygc2Nyb2xsaW5nXG4gICAgICAgICAgICAvLyBkZXZpY2UgdGhlIHVzZXIgdXNlcy5cbiAgICAgICAgICAgIGlmICh0eXBlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sodHlwZSwgLXZhbHVlLCBwb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gZS5kZWx0YVk7XG4gICAgICAgICAgICAvLyBGaXJlZm94IGRvdWJsZXMgdGhlIHZhbHVlcyBvbiByZXRpbmEgc2NyZWVucy4uLlxuICAgICAgICAgICAgaWYgKGZpcmVmb3ggJiYgZS5kZWx0YU1vZGUgPT09IHdpbmRvdy5XaGVlbEV2ZW50LkRPTV9ERUxUQV9QSVhFTCkgZGVsdGFZIC89IGJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gd2luZG93LldoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIGRlbHRhWSAqPSA0MDtcbiAgICAgICAgICAgIHNjcm9sbChkZWx0YVksIGUpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2V3aGVlbChlKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGFZID0gLWUud2hlZWxEZWx0YVk7XG4gICAgICAgICAgICBpZiAoc2FmYXJpKSBkZWx0YVkgPSBkZWx0YVkgLyAzO1xuICAgICAgICAgICAgc2Nyb2xsKGRlbHRhWSwgZSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbkludGVyYWN0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRlZCk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBDYW52YXMgPSByZXF1aXJlKCcuLi91dGlsL2NhbnZhcycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsL3V0aWwnKTtcbnZhciBicm93c2VyID0gcmVxdWlyZSgnLi4vdXRpbC9icm93c2VyJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG5cbnZhciBTdHlsZSA9IHJlcXVpcmUoJy4uL3N0eWxlL3N0eWxlJyk7XG52YXIgQW5pbWF0aW9uTG9vcCA9IHJlcXVpcmUoJy4uL3N0eWxlL2FuaW1hdGlvbl9sb29wJyk7XG52YXIgUGFpbnRlciA9IHJlcXVpcmUoJy4uL3JlbmRlci9wYWludGVyJyk7XG5cbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuLi9nZW8vdHJhbnNmb3JtJyk7XG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xudmFyIEhhbmRsZXJzID0gcmVxdWlyZSgnLi9oYW5kbGVycycpO1xudmFyIENhbWVyYSA9IHJlcXVpcmUoJy4vY2FtZXJhJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcbnZhciBMYXRMbmdCb3VuZHMgPSByZXF1aXJlKCcuLi9nZW8vbGF0X2xuZ19ib3VuZHMnKTtcbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG52YXIgQXR0cmlidXRpb24gPSByZXF1aXJlKCcuL2NvbnRyb2wvYXR0cmlidXRpb24nKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbWFwIGluc3RhbmNlLlxuICogQGNsYXNzIE1hcFxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbnRhaW5lciBIVE1MIGVsZW1lbnQgdG8gaW5pdGlhbGl6ZSB0aGUgbWFwIGluIChvciBlbGVtZW50IGlkIGFzIHN0cmluZylcbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW5ab29tPTBdIE1pbmltdW0gem9vbSBvZiB0aGUgbWFwXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4Wm9vbT0yMF0gTWF4aW11bSB6b29tIG9mIHRoZSBtYXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnN0eWxlIE1hcCBzdHlsZSBhbmQgZGF0YSBzb3VyY2UgZGVmaW5pdGlvbiAoZWl0aGVyIGEgSlNPTiBvYmplY3Qgb3IgYSBKU09OIFVSTCksIGRlc2NyaWJlZCBpbiB0aGUgW3N0eWxlIHJlZmVyZW5jZV0oaHR0cHM6Ly9tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuaGFzaD1mYWxzZV0gSWYgYHRydWVgLCB0aGUgbWFwIHdpbGwgdHJhY2sgYW5kIHVwZGF0ZSB0aGUgcGFnZSBVUkwgYWNjb3JkaW5nIHRvIG1hcCBwb3NpdGlvblxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbnRlcmFjdGl2ZT10cnVlXSBJZiBgZmFsc2VgLCBubyBtb3VzZSwgdG91Y2gsIG9yIGtleWJvYXJkIGxpc3RlbmVycyBhcmUgYXR0YWNoZWQgdG8gdGhlIG1hcCwgc28gaXQgd2lsbCBub3QgcmVzcG9uZCB0byBpbnB1dFxuICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5jbGFzc2VzIFN0eWxlIGNsYXNzIG5hbWVzIHdpdGggd2hpY2ggdG8gaW5pdGlhbGl6ZSB0aGUgbWFwXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9ZmFsc2VdIElmIGB0cnVlYCwgbWFwIGNyZWF0aW9uIHdpbGwgZmFpbCBpZiB0aGUgaW1wbGVtZW50YXRpb24gZGV0ZXJtaW5lcyB0aGF0IHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgY3JlYXRlZCBXZWJHTCBjb250ZXh0IHdvdWxkIGJlIGRyYW1hdGljYWxseSBsb3dlciB0aGFuIGV4cGVjdGVkLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXI9ZmFsc2VdIElmIGB0cnVlYCwgVGhlIG1hcHMgY2FudmFzIGNhbiBiZSBleHBvcnRlZCB0byBhIFBORyB1c2luZyBgbWFwLmdldENhbnZhcygpLnRvRGF0YVVSTCgpO2AuIFRoaXMgaXMgZmFsc2UgYnkgZGVmYXVsdCBhcyBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgbWFwID0gbmV3IG1hcGJveGdsLk1hcCh7XG4gKiAgIGNvbnRhaW5lcjogJ21hcCcsXG4gKiAgIGNlbnRlcjogWzM3Ljc3MjUzNywgLTEyMi40MjA2NzldLFxuICogICB6b29tOiAxMyxcbiAqICAgc3R5bGU6IHN0eWxlX29iamVjdCxcbiAqICAgaGFzaDogdHJ1ZVxuICogfSk7XG4gKi9cbnZhciBNYXAgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB1dGlsLmluaGVyaXQodGhpcy5vcHRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuYW5pbWF0aW9uTG9vcCA9IG5ldyBBbmltYXRpb25Mb29wKCk7XG4gICAgdGhpcy50cmFuc2Zvcm0gPSBuZXcgVHJhbnNmb3JtKG9wdGlvbnMubWluWm9vbSwgb3B0aW9ucy5tYXhab29tKTtcblxuICAgIGlmIChvcHRpb25zLm1heEJvdW5kcykge1xuICAgICAgICB2YXIgYiA9IExhdExuZ0JvdW5kcy5jb252ZXJ0KG9wdGlvbnMubWF4Qm91bmRzKTtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0ubGF0UmFuZ2UgPSBbYi5nZXRTb3V0aCgpLCBiLmdldE5vcnRoKCldO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybS5sbmdSYW5nZSA9IFtiLmdldFdlc3QoKSwgYi5nZXRFYXN0KCldO1xuICAgIH1cblxuICAgIHV0aWwuYmluZEFsbChbXG4gICAgICAgICdfZm9yd2FyZFN0eWxlRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRTb3VyY2VFdmVudCcsXG4gICAgICAgICdfZm9yd2FyZExheWVyRXZlbnQnLFxuICAgICAgICAnX2ZvcndhcmRUaWxlRXZlbnQnLFxuICAgICAgICAnX29uU3R5bGVMb2FkJyxcbiAgICAgICAgJ19vblN0eWxlQ2hhbmdlJyxcbiAgICAgICAgJ19vblNvdXJjZUFkZCcsXG4gICAgICAgICdfb25Tb3VyY2VSZW1vdmUnLFxuICAgICAgICAnX29uU291cmNlVXBkYXRlJyxcbiAgICAgICAgJ3VwZGF0ZScsXG4gICAgICAgICdyZW5kZXInXG4gICAgXSwgdGhpcyk7XG5cbiAgICB0aGlzLl9zZXR1cENvbnRhaW5lcigpO1xuICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuXG4gICAgdGhpcy5vbignbW92ZScsIHRoaXMudXBkYXRlKTtcbiAgICB0aGlzLm9uKCd6b29tJywgdGhpcy51cGRhdGUuYmluZCh0aGlzLCB0cnVlKSk7XG4gICAgdGhpcy5vbignbW92ZWVuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkxvb3Auc2V0KDMwMCk7IC8vIHRleHQgZmFkaW5nXG4gICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuaGFuZGxlcnMgPSBvcHRpb25zLmludGVyYWN0aXZlICYmIG5ldyBIYW5kbGVycyh0aGlzKTtcblxuICAgIHRoaXMuX2hhc2ggPSBvcHRpb25zLmhhc2ggJiYgKG5ldyBIYXNoKCkpLmFkZFRvKHRoaXMpO1xuICAgIC8vIGRvbid0IHNldCBwb3NpdGlvbiBmcm9tIG9wdGlvbnMgaWYgc2V0IHRocm91Z2ggaGFzaFxuICAgIGlmICghdGhpcy5faGFzaCB8fCAhdGhpcy5faGFzaC5fb25IYXNoQ2hhbmdlKCkpIHtcbiAgICAgICAgdGhpcy5qdW1wVG8ob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3VyY2VzID0ge307XG4gICAgdGhpcy5zdGFja3MgPSB7fTtcbiAgICB0aGlzLl9jbGFzc2VzID0ge307XG5cbiAgICB0aGlzLnJlc2l6ZSgpO1xuXG4gICAgaWYgKG9wdGlvbnMuY2xhc3NlcykgdGhpcy5zZXRDbGFzc2VzKG9wdGlvbnMuY2xhc3Nlcyk7XG4gICAgaWYgKG9wdGlvbnMuc3R5bGUpIHRoaXMuc2V0U3R5bGUob3B0aW9ucy5zdHlsZSk7XG4gICAgaWYgKG9wdGlvbnMuYXR0cmlidXRpb25Db250cm9sKSB0aGlzLmFkZENvbnRyb2wobmV3IEF0dHJpYnV0aW9uKCkpO1xufTtcblxudXRpbC5leHRlbmQoTWFwLnByb3RvdHlwZSwgRXZlbnRlZCk7XG51dGlsLmV4dGVuZChNYXAucHJvdG90eXBlLCBDYW1lcmEucHJvdG90eXBlKTtcbnV0aWwuZXh0ZW5kKE1hcC5wcm90b3R5cGUsIC8qKiBAbGVuZHMgTWFwLnByb3RvdHlwZSAqL3tcblxuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgY2VudGVyOiBbMCwgMF0sXG4gICAgICAgIHpvb206IDAsXG4gICAgICAgIGJlYXJpbmc6IDAsXG4gICAgICAgIHBpdGNoOiAwLFxuXG4gICAgICAgIG1pblpvb206IDAsXG4gICAgICAgIG1heFpvb206IDIwLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICBoYXNoOiBmYWxzZSxcblxuICAgICAgICBhdHRyaWJ1dGlvbkNvbnRyb2w6IHRydWUsXG5cbiAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogZmFsc2UsXG4gICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2VcbiAgICB9LFxuXG4gICAgYWRkQ29udHJvbDogZnVuY3Rpb24oY29udHJvbCkge1xuICAgICAgICBjb250cm9sLmFkZFRvKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHR5cGVkZWYge09iamVjdH0gW3N0eWxlT3B0aW9uc11cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtzdHlsZU9wdGlvbnMudHJhbnNpdGlvbj10cnVlXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHN0eWxlIGNsYXNzIHRvIGEgbWFwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2xhc3MgbmFtZSBvZiBzdHlsZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7c3R5bGVPcHRpb25zfSBvcHRpb25zXG4gICAgICogQGZpcmVzIGNoYW5nZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZENsYXNzOiBmdW5jdGlvbihrbGFzcywgb3B0aW9ucykge1xuICAgICAgICBpZiAodGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc10gPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIHN0eWxlIGNsYXNzIGZyb20gYSBtYXBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBuYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghdGhpcy5fY2xhc3Nlc1trbGFzc10pIHJldHVybjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgICAgICBpZiAodGhpcy5zdHlsZSkgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzLCBvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSGVscGVyIG1ldGhvZCB0byBhZGQgbW9yZSB0aGFuIG9uZSBjbGFzc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBrbGFzc2VzIEFuIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICogQHBhcmFtIHtzdHlsZU9wdGlvbnN9IG9wdGlvbnNcbiAgICAgKiBAZmlyZXMgY2hhbmdlXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0Q2xhc3NlczogZnVuY3Rpb24oa2xhc3Nlcywgb3B0aW9ucykge1xuICAgICAgICB0aGlzLl9jbGFzc2VzID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5fY2xhc3Nlc1trbGFzc2VzW2ldXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcywgb3B0aW9ucyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENoZWNrIHdoZXRoZXIgYSBzdHlsZSBjbGFzcyBpcyBhY3RpdmVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrbGFzcyBOYW1lIG9mIHN0eWxlIGNsYXNzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaGFzQ2xhc3M6IGZ1bmN0aW9uKGtsYXNzKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2NsYXNzZXNba2xhc3NdO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgYWN0aXZlIHN0eWxlIGNsYXNzZXNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGdldENsYXNzZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fY2xhc3Nlcyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIERldGVjdCB0aGUgbWFwJ3MgbmV3IHdpZHRoIGFuZCBoZWlnaHQgYW5kIHJlc2l6ZSBpdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlc2l6ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDAsIGhlaWdodCA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xuICAgICAgICAgICAgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGggfHwgNDAwO1xuICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAzMDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jYW52YXMucmVzaXplKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMudHJhbnNmb3JtLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0uX2NvbnN0cmFpbigpO1xuXG4gICAgICAgIHRoaXMucGFpbnRlci5yZXNpemUod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIC5maXJlKCdtb3Zlc3RhcnQnKVxuICAgICAgICAgICAgLmZpcmUoJ21vdmUnKVxuICAgICAgICAgICAgLmZpcmUoJ3Jlc2l6ZScpXG4gICAgICAgICAgICAuZmlyZSgnbW92ZWVuZCcpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1hcCdzIGdlb2dyYXBoaWNhbCBib3VuZHNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtMYXRMbmdCb3VuZHN9XG4gICAgICovXG4gICAgZ2V0Qm91bmRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKG5ldyBQb2ludCgwLCAwKSksXG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybS5wb2ludExvY2F0aW9uKHRoaXMudHJhbnNmb3JtLnNpemUpKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHBpeGVsIGNvb3JkaW5hdGVzIChyZWxhdGl2ZSB0byBtYXAgY29udGFpbmVyKSBnaXZlbiBhIGdlb2dyYXBoaWNhbCBsb2NhdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IGB4YCBhbmQgYHlgIGNvb3JkaW5hdGVzXG4gICAgICovXG4gICAgcHJvamVjdDogZnVuY3Rpb24obGF0bG5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybS5sb2NhdGlvblBvaW50KExhdExuZy5jb252ZXJ0KGxhdGxuZykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGdpdmVuIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHBvaW50IFt4LCB5XSBwaXhlbCBjb29yZGluYXRlc1xuICAgICAqIEByZXR1cm5zIHtMYXRMbmd9XG4gICAgICovXG4gICAgdW5wcm9qZWN0OiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbihQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZmVhdHVyZXMgYXQgYSBwb2ludCAoW3gsIHldKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBwb2ludCBbeCwgeV0gcGl4ZWwgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwYXJhbXMucmFkaXVzPTBdIE9wdGlvbmFsLiBSYWRpdXMgaW4gcGl4ZWxzIHRvIHNlYXJjaCBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMubGF5ZXIgT3B0aW9uYWwuIE9ubHkgcmV0dXJuIGZlYXR1cmVzIGZyb20gYSBnaXZlbiBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMudHlwZSBPcHRpb25hbC4gRWl0aGVyIGByYXN0ZXJgIG9yIGB2ZWN0b3JgXG4gICAgICogQHBhcmFtIHtmZWF0dXJlc0F0Q2FsbGJhY2t9IGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcmVzcG9uc2VcbiAgICAgKlxuICAgICAqIEBjYWxsYmFjayBmZWF0dXJlc0F0Q2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge09iamVjdHxudWxsfSBlcnIgRXJyb3IgX0lmIGFueV9cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmZWF0dXJlcyBEaXNwbGF5cyBhIEpTT04gYXJyYXkgb2YgZmVhdHVyZXMgZ2l2ZW4gdGhlIHBhc3NlZCBwYXJhbWV0ZXJzIG9mIGBmZWF0dXJlc0F0YFxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIG1hcC5mZWF0dXJlc0F0KFsxMCwgMjBdLCB7IHJhZGl1czogMTAgfSwgZnVuY3Rpb24oZXJyLCBmZWF0dXJlcykge1xuICAgICAqICAgY29uc29sZS5sb2coZmVhdHVyZXMpO1xuICAgICAqIH0pO1xuICAgICAqL1xuICAgIGZlYXR1cmVzQXQ6IGZ1bmN0aW9uKHBvaW50LCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBjb29yZCA9IHRoaXMudHJhbnNmb3JtLnBvaW50Q29vcmRpbmF0ZShQb2ludC5jb252ZXJ0KHBvaW50KSk7XG4gICAgICAgIHRoaXMuc3R5bGUuZmVhdHVyZXNBdChjb29yZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgbWFwJ3Mgc3R5bGUgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3R5bGUgQSBzdHlsZSBvYmplY3QgZm9ybWF0dGVkIGFzIEpTT05cbiAgICAgKiBAcmV0dXJucyB7TWFwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRTdHlsZTogZnVuY3Rpb24oc3R5bGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGVcbiAgICAgICAgICAgICAgICAub2ZmKCdsb2FkJywgdGhpcy5fb25TdHlsZUxvYWQpXG4gICAgICAgICAgICAgICAgLm9mZignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vblN0eWxlQ2hhbmdlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ3NvdXJjZS5hZGQnLCB0aGlzLl9vblNvdXJjZUFkZClcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmxvYWQnLCB0aGlzLl9vblNvdXJjZVVwZGF0ZSlcbiAgICAgICAgICAgICAgICAub2ZmKCdzb3VyY2UuZXJyb3InLCB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLmFkZCcsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ2xheWVyLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRMYXllckV2ZW50KVxuICAgICAgICAgICAgICAgIC5vZmYoJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgICAgICAub2ZmKCd0aWxlLnJlbW92ZScsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5sb2FkJywgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICAgICAgLm9mZigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpXG4gICAgICAgICAgICAgICAgLl9yZW1vdmUoKTtcblxuICAgICAgICAgICAgdGhpcy5vZmYoJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5vZmYoJ3BpdGNoJywgdGhpcy5zdHlsZS5fcmVkb1BsYWNlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN0eWxlKSB7XG4gICAgICAgICAgICB0aGlzLnN0eWxlID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2UgaWYgKHN0eWxlIGluc3RhbmNlb2YgU3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBzdHlsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3R5bGUgPSBuZXcgU3R5bGUoc3R5bGUsIHRoaXMuYW5pbWF0aW9uTG9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0eWxlXG4gICAgICAgICAgICAub24oJ2xvYWQnLCB0aGlzLl9vblN0eWxlTG9hZClcbiAgICAgICAgICAgIC5vbignZXJyb3InLCB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudClcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdGhpcy5fb25TdHlsZUNoYW5nZSlcbiAgICAgICAgICAgIC5vbignc291cmNlLmFkZCcsIHRoaXMuX29uU291cmNlQWRkKVxuICAgICAgICAgICAgLm9uKCdzb3VyY2UucmVtb3ZlJywgdGhpcy5fb25Tb3VyY2VSZW1vdmUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5sb2FkJywgdGhpcy5fb25Tb3VyY2VVcGRhdGUpXG4gICAgICAgICAgICAub24oJ3NvdXJjZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudClcbiAgICAgICAgICAgIC5vbignc291cmNlLmNoYW5nZScsIHRoaXMuX29uU291cmNlVXBkYXRlKVxuICAgICAgICAgICAgLm9uKCdsYXllci5hZGQnLCB0aGlzLl9mb3J3YXJkTGF5ZXJFdmVudClcbiAgICAgICAgICAgIC5vbignbGF5ZXIucmVtb3ZlJywgdGhpcy5fZm9yd2FyZExheWVyRXZlbnQpXG4gICAgICAgICAgICAub24oJ3RpbGUuYWRkJywgdGhpcy5fZm9yd2FyZFRpbGVFdmVudClcbiAgICAgICAgICAgIC5vbigndGlsZS5yZW1vdmUnLCB0aGlzLl9mb3J3YXJkVGlsZUV2ZW50KVxuICAgICAgICAgICAgLm9uKCd0aWxlLmxvYWQnLCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIC5vbigndGlsZS5lcnJvcicsIHRoaXMuX2ZvcndhcmRUaWxlRXZlbnQpO1xuXG4gICAgICAgIHRoaXMub24oJ3JvdGF0ZScsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuICAgICAgICB0aGlzLm9uKCdwaXRjaCcsIHRoaXMuc3R5bGUuX3JlZG9QbGFjZW1lbnQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBzb3VyY2UgdG8gdGhlIG1hcCBzdHlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJRCBvZiB0aGUgc291cmNlLiBNdXN0IG5vdCBiZSB1c2VkIGJ5IGFueSBleGlzdGluZyBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBzb3VyY2Ugc3BlY2lmaWNhdGlvbiwgZm9sbG93aW5nIHRoZVxuICAgICAqIFtNYXBib3ggR0wgU3R5bGUgUmVmZXJlbmNlXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNzb3VyY2VzKVxuICAgICAqIEBmaXJlcyBzb3VyY2UuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkU291cmNlOiBmdW5jdGlvbihpZCwgc291cmNlKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuYWRkU291cmNlKGlkLCBzb3VyY2UpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFuIGV4aXN0aW5nIHNvdXJjZSBmcm9tIHRoZSBtYXAgc3R5bGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSUQgb2YgdGhlIHNvdXJjZSB0byByZW1vdmVcbiAgICAgKiBAZmlyZXMgc291cmNlLnJlbW92ZVxuICAgICAqIEByZXR1cm5zIHtNYXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZVNvdXJjZTogZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5yZW1vdmVTb3VyY2UoaWQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBzdHlsZSBzb3VyY2Ugb2JqZWN0IHdpdGggdGhlIGdpdmVuIGBpZGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgc291cmNlIElEXG4gICAgICogQHJldHVybnMge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXRTb3VyY2U6IGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFNvdXJjZShpZCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGxheWVyIHRvIHRoZSBtYXAgc3R5bGUuIFRoZSBsYXllciB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGUgbGF5ZXIgd2l0aFxuICAgICAqIElEIGBiZWZvcmVgLCBvciBhcHBlbmRlZCBpZiBgYmVmb3JlYCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7U3R5bGVMYXllcnxPYmplY3R9IGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSBiZWZvcmUgIElEIG9mIGFuIGV4aXN0aW5nIGxheWVyIHRvIGluc2VydCBiZWZvcmVcbiAgICAgKiBAZmlyZXMgbGF5ZXIuYWRkXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgYWRkTGF5ZXI6IGZ1bmN0aW9uKGxheWVyLCBiZWZvcmUpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5hZGRMYXllcihsYXllciwgYmVmb3JlKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gYGlkYCBmcm9tIHRoZSBtYXAuIEFueSBsYXllcnMgd2hpY2ggcmVmZXIgdG8gdGhlXG4gICAgICogc3BlY2lmaWVkIGxheWVyIHZpYSBhIGByZWZgIHByb3BlcnR5IGFyZSBhbHNvIHJlbW92ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgbGF5ZXIgaWRcbiAgICAgKiBAZmlyZXMgbGF5ZXIucmVtb3ZlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZUxheWVyOiBmdW5jdGlvbihpZCkge1xuICAgICAgICB0aGlzLnN0eWxlLnJlbW92ZUxheWVyKGlkKTtcbiAgICAgICAgdGhpcy5zdHlsZS5fY2FzY2FkZSh0aGlzLl9jbGFzc2VzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZmlsdGVyIGZvciBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXIgZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0RmlsdGVyOiBmdW5jdGlvbihsYXllciwgZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuc3R5bGUuc2V0RmlsdGVyKGxheWVyLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBmaWx0ZXIgZm9yIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZmlsdGVyIHNwZWNpZmljYXRpb24sIGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLyNmaWx0ZXIpXG4gICAgICovXG4gICAgZ2V0RmlsdGVyOiBmdW5jdGlvbihsYXllcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHlsZS5nZXRGaWx0ZXIobGF5ZXIpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHZhbHVlIG9mIGEgcGFpbnQgcHJvcGVydHkgaW4gYSBnaXZlbiBzdHlsZSBsYXllci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYXllciBJRCBvZiBhIGxheWVyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgbmFtZSBvZiBhIHBhaW50IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIHBhaW50IHByb3Blcnk7IG11c3QgaGF2ZSB0aGUgdHlwZSBhcHByb3ByaWF0ZSBmb3IgdGhlIHByb3BlcnR5IGFzIGRlZmluZWQgaW4gdGhlIFtTdHlsZSBTcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5tYXBib3guY29tL21hcGJveC1nbC1zdHlsZS1zcGVjLylcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcykge1xuICAgICAgICB0aGlzLnN0eWxlLnNldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIHZhbHVlLCBrbGFzcyk7XG4gICAgICAgIHRoaXMuc3R5bGUuX2Nhc2NhZGUodGhpcy5fY2xhc3Nlcyk7XG4gICAgICAgIHRoaXMudXBkYXRlKHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB2YWx1ZSBvZiBhIHBhaW50IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBwYWludCBwcm9wZXJ0eVxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0ga2xhc3Mgb3B0aW9uYWwgY2xhc3Mgc3BlY2lmaWVyIGZvciB0aGUgcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7Kn0gdmFsdWUgZm9yIHRoZSBwYWludCBwcm9wZXJ5XG4gICAgICovXG4gICAgZ2V0UGFpbnRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUsIGtsYXNzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0eWxlLmdldFBhaW50UHJvcGVydHkobGF5ZXIsIG5hbWUsIGtsYXNzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSB2YWx1ZSBvZiBhIGxheW91dCBwcm9wZXJ0eSBpbiBhIGdpdmVuIHN0eWxlIGxheWVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxheWVyIElEIG9mIGEgbGF5ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIGEgbGF5b3V0IHByb3BlcnR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSB2YWx1ZSBmb3IgdGhlIGxheW91dCBwcm9wZXJ5OyBtdXN0IGhhdmUgdGhlIHR5cGUgYXBwcm9wcmlhdGUgZm9yIHRoZSBwcm9wZXJ0eSBhcyBkZWZpbmVkIGluIHRoZSBbU3R5bGUgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cubWFwYm94LmNvbS9tYXBib3gtZ2wtc3R5bGUtc3BlYy8pXG4gICAgICogQHJldHVybnMge01hcH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF5b3V0UHJvcGVydHk6IGZ1bmN0aW9uKGxheWVyLCBuYW1lLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnN0eWxlLnNldExheW91dFByb3BlcnR5KGxheWVyLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHZhbHVlIG9mIGEgbGF5b3V0IHByb3BlcnR5IGluIGEgZ2l2ZW4gc3R5bGUgbGF5ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF5ZXIgSUQgb2YgYSBsYXllclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIG5hbWUgb2YgYSBsYXlvdXQgcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGtsYXNzIG9wdGlvbmFsIGNsYXNzIHNwZWNpZmllciBmb3IgdGhlIHByb3BlcnR5XG4gICAgICogQHJldHVybnMgeyp9IHZhbHVlIGZvciB0aGUgbGF5b3V0IHByb3BlcnlcbiAgICAgKi9cbiAgICBnZXRMYXlvdXRQcm9wZXJ0eTogZnVuY3Rpb24obGF5ZXIsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGF5b3V0UHJvcGVydHkobGF5ZXIsIG5hbWUpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIE1hcCdzIGNvbnRhaW5lciBhcyBhbiBIVE1MIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGFpbmVyIGZvciB0aGUgbWFwIGBjYW52YXNgIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBhZGQgbm9uLUdMIG92ZXJsYXlzIHRvIHRoZSBtYXAsIHlvdSBzaG91bGQgYXBwZW5kIHRoZW0gdG8gdGhpcyBlbGVtZW50LiBUaGlzXG4gICAgICogaXMgdGhlIGVsZW1lbnQgdG8gd2hpY2ggZXZlbnQgYmluZGluZ3MgZm9yIG1hcCBpbnRlcmFjdGl2aXR5IHN1Y2ggYXMgcGFubmluZyBhbmQgem9vbWluZyBhcmVcbiAgICAgKiBhdHRhY2hlZC4gSXQgd2lsbCByZWNlaXZlIGJ1YmJsZWQgZXZlbnRzIGZvciBjaGlsZCBlbGVtZW50cyBzdWNoIGFzIHRoZSBgY2FudmFzYCwgYnV0IG5vdCBmb3JcbiAgICAgKiBtYXAgY29udHJvbHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lclxuICAgICAqL1xuICAgIGdldENhbnZhc0NvbnRhaW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYW52YXNDb250YWluZXI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgTWFwJ3MgY2FudmFzIGFzIGFuIEhUTUwgY2FudmFzXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fSBjYW52YXNcbiAgICAgKi9cbiAgICBnZXRDYW52YXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FudmFzLmdldEVsZW1lbnQoKTtcbiAgICB9LFxuXG4gICAgX3NldHVwQ29udGFpbmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGlkID0gdGhpcy5vcHRpb25zLmNvbnRhaW5lcjtcblxuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xuICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtbWFwJyk7XG5cbiAgICAgICAgdmFyIGNhbnZhc0NvbnRhaW5lciA9IHRoaXMuX2NhbnZhc0NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jYW52YXMtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgY2FudmFzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWludGVyYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2FudmFzID0gbmV3IENhbnZhcyh0aGlzLCBjYW52YXNDb250YWluZXIpO1xuXG4gICAgICAgIHZhciBjb250cm9sQ29udGFpbmVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLWNvbnRyb2wtY29udGFpbmVyJywgY29udGFpbmVyKTtcbiAgICAgICAgdmFyIGNvcm5lcnMgPSB0aGlzLl9jb250cm9sQ29ybmVycyA9IHt9O1xuICAgICAgICBbJ3RvcC1sZWZ0JywgJ3RvcC1yaWdodCcsICdib3R0b20tbGVmdCcsICdib3R0b20tcmlnaHQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIGNvcm5lcnNbcG9zXSA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1jdHJsLScgKyBwb3MsIGNvbnRyb2xDb250YWluZXIpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgX3NldHVwUGFpbnRlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnbCA9IHRoaXMuX2NhbnZhcy5nZXRXZWJHTENvbnRleHQoe1xuICAgICAgICAgICAgZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDogdGhpcy5vcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQsXG4gICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRoaXMub3B0aW9ucy5wcmVzZXJ2ZURyYXdpbmdCdWZmZXJcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFnbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0wnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFpbnRlciA9IG5ldyBQYWludGVyKGdsLCB0aGlzLnRyYW5zZm9ybSk7XG4gICAgfSxcblxuICAgIF9jb250ZXh0TG9zdDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZyYW1lSWQpIHtcbiAgICAgICAgICAgIGJyb3dzZXIuY2FuY2VsRnJhbWUodGhpcy5fZnJhbWVJZCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbnRleHRSZXN0b3JlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuX3NldHVwUGFpbnRlcigpO1xuICAgICAgICB0aGlzLnJlc2l6ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJcyB0aGlzIG1hcCBmdWxseSBsb2FkZWQ/IElmIHRoZSBzdHlsZSBpc24ndCBsb2FkZWRcbiAgICAgKiBvciBpdCBoYXMgYSBjaGFuZ2UgdG8gdGhlIHNvdXJjZXMgb3Igc3R5bGUgdGhhdCBpc24ndFxuICAgICAqIHByb3BhZ2F0ZWQgdG8gaXRzIHN0eWxlLCByZXR1cm4gZmFsc2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gd2hldGhlciB0aGUgbWFwIGlzIGxvYWRlZFxuICAgICAqL1xuICAgIGxvYWRlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHlsZURpcnR5IHx8IHRoaXMuX3NvdXJjZXNEaXJ0eSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuc3R5bGUgJiYgIXRoaXMuc3R5bGUubG9hZGVkKCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhpcyBtYXAncyBzdHlsZSBhbmQgcmUtcmVuZGVyIHRoZSBtYXAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdXBkYXRlU3R5bGUgbmV3IHN0eWxlXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24odXBkYXRlU3R5bGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0eWxlKSByZXR1cm4gdGhpcztcblxuICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gdGhpcy5fc3R5bGVEaXJ0eSB8fCB1cGRhdGVTdHlsZTtcbiAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLl9yZXJlbmRlcigpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHdoZW4gYSAocmUtKXJlbmRlciBvZiB0aGUgbWFwIGlzIHJlcXVpcmVkLCBlLmcuIHdoZW4gdGhlXG4gICAgICogdXNlciBwYW5uZWQgb3Igem9vbWVkLGYgb3IgbmV3IGRhdGEgaXMgYXZhaWxhYmxlLlxuICAgICAqIEByZXR1cm5zIHtNYXB9IHRoaXNcbiAgICAgKi9cbiAgICByZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiB0aGlzLl9zdHlsZURpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZURpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnN0eWxlLl9yZWNhbGN1bGF0ZSh0aGlzLnRyYW5zZm9ybS56b29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnN0eWxlICYmIHRoaXMuX3NvdXJjZXNEaXJ0eSAmJiAhdGhpcy5fc291cmNlc0RpcnR5VGltZW91dCkge1xuICAgICAgICAgICAgdGhpcy5fc291cmNlc0RpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VzRGlydHlUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSwgNTApO1xuICAgICAgICAgICAgdGhpcy5zdHlsZS5fdXBkYXRlU291cmNlcyh0aGlzLnRyYW5zZm9ybSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhaW50ZXIucmVuZGVyKHRoaXMuc3R5bGUsIHtcbiAgICAgICAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxuICAgICAgICAgICAgdmVydGljZXM6IHRoaXMudmVydGljZXMsXG4gICAgICAgICAgICByb3RhdGluZzogdGhpcy5yb3RhdGluZyxcbiAgICAgICAgICAgIHpvb21pbmc6IHRoaXMuem9vbWluZ1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmZpcmUoJ3JlbmRlcicpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRlZCgpICYmICF0aGlzLl9sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmZpcmUoJ2xvYWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2ZyYW1lSWQgPSBudWxsO1xuXG4gICAgICAgIGlmICghdGhpcy5hbmltYXRpb25Mb29wLnN0b3BwZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fc3R5bGVEaXJ0eSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fc291cmNlc0RpcnR5IHx8IHRoaXMuX3JlcGFpbnQgfHwgIXRoaXMuYW5pbWF0aW9uTG9vcC5zdG9wcGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlcmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRGVzdHJveXMgdGhlIG1hcCdzIHVuZGVybHlpbmcgcmVzb3VyY2VzLCBpbmNsdWRpbmcgd2ViIHdvcmtlcnMuXG4gICAgICogQHJldHVybnMge01hcH0gdGhpc1xuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9oYXNoKSB0aGlzLl9oYXNoLnJlbW92ZSgpO1xuICAgICAgICBicm93c2VyLmNhbmNlbEZyYW1lKHRoaXMuX2ZyYW1lSWQpO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fc291cmNlc0RpcnR5VGltZW91dCk7XG4gICAgICAgIHRoaXMuc2V0U3R5bGUobnVsbCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcmVyZW5kZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zdHlsZSAmJiAhdGhpcy5fZnJhbWVJZCkge1xuICAgICAgICAgICAgdGhpcy5fZnJhbWVJZCA9IGJyb3dzZXIuZnJhbWUodGhpcy5yZW5kZXIpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU3R5bGVFdmVudDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmZpcmUoJ3N0eWxlLicgKyBlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkU291cmNlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy5maXJlKGUudHlwZSwgdXRpbC5leHRlbmQoe3N0eWxlOiBlLnRhcmdldH0sIGUpKTtcbiAgICB9LFxuXG4gICAgX2ZvcndhcmRMYXllckV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9mb3J3YXJkVGlsZUV2ZW50OiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMuZmlyZShlLnR5cGUsIHV0aWwuZXh0ZW5kKHtzdHlsZTogZS50YXJnZXR9LCBlKSk7XG4gICAgfSxcblxuICAgIF9vblN0eWxlTG9hZDogZnVuY3Rpb24oZSkge1xuICAgICAgICB0aGlzLnN0eWxlLl9jYXNjYWRlKHRoaXMuX2NsYXNzZXMsIHt0cmFuc2l0aW9uOiBmYWxzZX0pO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU3R5bGVFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU3R5bGVDaGFuZ2U6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGUodHJ1ZSk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTdHlsZUV2ZW50KGUpO1xuICAgIH0sXG5cbiAgICBfb25Tb3VyY2VBZGQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGUuc291cmNlO1xuICAgICAgICBpZiAoc291cmNlLm9uQWRkKVxuICAgICAgICAgICAgc291cmNlLm9uQWRkKHRoaXMpO1xuICAgICAgICB0aGlzLl9mb3J3YXJkU291cmNlRXZlbnQoZSk7XG4gICAgfSxcblxuICAgIF9vblNvdXJjZVJlbW92ZTogZnVuY3Rpb24oZSkge1xuICAgICAgICB2YXIgc291cmNlID0gZS5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2Uub25SZW1vdmUpXG4gICAgICAgICAgICBzb3VyY2Uub25SZW1vdmUodGhpcyk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9LFxuXG4gICAgX29uU291cmNlVXBkYXRlOiBmdW5jdGlvbihlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIHRoaXMuX2ZvcndhcmRTb3VyY2VFdmVudChlKTtcbiAgICB9XG59KTtcblxudXRpbC5leHRlbmRBbGwoTWFwLnByb3RvdHlwZSwge1xuXG4gICAgLyoqXG4gICAgICogRW5hYmxlIGRlYnVnZ2luZyBtb2RlXG4gICAgICpcbiAgICAgKiBAbmFtZSBkZWJ1Z1xuICAgICAqIEBtZW1iZXJvZiBNYXBcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfZGVidWc6IGZhbHNlLFxuICAgIGdldCBkZWJ1ZygpIHsgcmV0dXJuIHRoaXMuX2RlYnVnOyB9LFxuICAgIHNldCBkZWJ1Zyh2YWx1ZSkgeyB0aGlzLl9kZWJ1ZyA9IHZhbHVlOyB0aGlzLnVwZGF0ZSgpOyB9LFxuXG4gICAgLyoqXG4gICAgICogU2hvdyBjb2xsaXNpb24gYm94ZXM6IHVzZWZ1bCBmb3IgZGVidWdnaW5nIGxhYmVsIHBsYWNlbWVudFxuICAgICAqIGluIHN0eWxlcy5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbGxpc2lvbkRlYnVnXG4gICAgICogQG1lbWJlcm9mIE1hcFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIF9jb2xsaXNpb25EZWJ1ZzogZmFsc2UsXG4gICAgZ2V0IGNvbGxpc2lvbkRlYnVnKCkgeyByZXR1cm4gdGhpcy5fY29sbGlzaW9uRGVidWc7IH0sXG4gICAgc2V0IGNvbGxpc2lvbkRlYnVnKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbGxpc2lvbkRlYnVnID0gdmFsdWU7XG4gICAgICAgIGZvciAodmFyIGkgaW4gdGhpcy5zdHlsZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHlsZS5zb3VyY2VzW2ldLnJlbG9hZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3R5bGUuc291cmNlc1tpXS5yZWxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBFbmFibGUgY29udGludW91cyByZXBhaW50IHRvIGFuYWx5emUgcGVyZm9ybWFuY2VcbiAgICAgKlxuICAgICAqIEBuYW1lIHJlcGFpbnRcbiAgICAgKiBAbWVtYmVyb2YgTWFwXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3JlcGFpbnQ6IGZhbHNlLFxuICAgIGdldCByZXBhaW50KCkgeyByZXR1cm4gdGhpcy5fcmVwYWludDsgfSxcbiAgICBzZXQgcmVwYWludCh2YWx1ZSkgeyB0aGlzLl9yZXBhaW50ID0gdmFsdWU7IHRoaXMudXBkYXRlKCk7IH0sXG5cbiAgICAvLyBzaG93IHZlcnRpY2VzXG4gICAgX3ZlcnRpY2VzOiBmYWxzZSxcbiAgICBnZXQgdmVydGljZXMoKSB7IHJldHVybiB0aGlzLl92ZXJ0aWNlczsgfSxcbiAgICBzZXQgdmVydGljZXModmFsdWUpIHsgdGhpcy5fdmVydGljZXMgPSB2YWx1ZTsgdGhpcy51cGRhdGUoKTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9wdXA7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbC91dGlsJyk7XG52YXIgRXZlbnRlZCA9IHJlcXVpcmUoJy4uL3V0aWwvZXZlbnRlZCcpO1xudmFyIERPTSA9IHJlcXVpcmUoJy4uL3V0aWwvZG9tJyk7XG52YXIgTGF0TG5nID0gcmVxdWlyZSgnLi4vZ2VvL2xhdF9sbmcnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgcG9wdXAgY29tcG9uZW50XG4gKiBAY2xhc3MgUG9wdXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuY2xvc2VCdXR0b25cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gb3B0aW9ucy5jbG9zZU9uQ2xpY2tcbiAqIEBleGFtcGxlXG4gKiB2YXIgdG9vbHRpcCA9IG5ldyBtYXBib3hnbC5Qb3B1cCgpXG4gKiAgIC5zZXRMYXRMbmcobWFwLnVucHJvamVjdChlLnBvaW50KSlcbiAqICAgLnNldEhUTUwoXCI8aDE+SGVsbG8gV29ybGQhPC9oMT5cIilcbiAqICAgLmFkZFRvKG1hcCk7XG4gKi9cbmZ1bmN0aW9uIFBvcHVwKG9wdGlvbnMpIHtcbiAgICB1dGlsLnNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG4gICAgdXRpbC5iaW5kQWxsKFtcbiAgICAgICAgJ191cGRhdGVQb3NpdGlvbicsXG4gICAgICAgICdfb25DbGlja0Nsb3NlJ10sXG4gICAgICAgIHRoaXMpO1xufVxuXG5Qb3B1cC5wcm90b3R5cGUgPSB1dGlsLmluaGVyaXQoRXZlbnRlZCwgLyoqIEBsZW5kcyBQb3B1cC5wcm90b3R5cGUgKi97XG4gICAgb3B0aW9uczoge1xuICAgICAgICBjbG9zZUJ1dHRvbjogdHJ1ZSxcbiAgICAgICAgY2xvc2VPbkNsaWNrOiB0cnVlXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIHRoZSBwb3B1cCB0byBhIG1hcFxuICAgICAqIEBwYXJhbSB7TWFwfSBtYXBcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIGFkZFRvOiBmdW5jdGlvbihtYXApIHtcbiAgICAgICAgdGhpcy5fbWFwID0gbWFwO1xuICAgICAgICB0aGlzLl9tYXAub24oJ21vdmUnLCB0aGlzLl91cGRhdGVQb3NpdGlvbik7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub24oJ2NsaWNrJywgdGhpcy5fb25DbGlja0Nsb3NlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHBvcHVwIGZyb20gdGhlIG1hcFxuICAgICAqIEBleGFtcGxlXG4gICAgICogdmFyIHBvcHVwID0gbmV3IG1hcGJveGdsLlBvcHVwKCkuYWRkVG8obWFwKTtcbiAgICAgKiBwb3B1cC5yZW1vdmUoKTtcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fbWFwKSB7XG4gICAgICAgICAgICB0aGlzLl9tYXAub2ZmKCdtb3ZlJywgdGhpcy5fdXBkYXRlUG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy5fbWFwLm9mZignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX21hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgY29vcmRpbmF0ZXMgb2YgcG9wdXAgZWxlbWVudCByZWxhdGl2ZSB0byBtYXBcbiAgICAgKiBAcmV0dXJucyB7TGF0TG5nfVxuICAgICAqL1xuICAgIGdldExhdExuZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYXRMbmc7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY29vcmRpbmF0ZXMgb2YgYSBwb3B1cCBlbGVtZW50IHRvIGEgbWFwXG4gICAgICogQHBhcmFtIHtMYXRMbmd9IGxhdGxuZ1xuICAgICAqIEByZXR1cm5zIHtQb3B1cH0gYHRoaXNgXG4gICAgICovXG4gICAgc2V0TGF0TG5nOiBmdW5jdGlvbihsYXRsbmcpIHtcbiAgICAgICAgdGhpcy5fbGF0TG5nID0gTGF0TG5nLmNvbnZlcnQobGF0bG5nKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIHRleHQgb25seSBjb250ZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAgICAgKiBAcmV0dXJucyB7UG9wdXB9IGB0aGlzYFxuICAgICAqL1xuICAgIHNldFRleHQ6IGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgdGhpcy5fY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBGaWxsIGEgcG9wdXAgZWxlbWVudCB3aXRoIEhUTUwgY29udGVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG4gICAgICogQHJldHVybnMge1BvcHVwfSBgdGhpc2BcbiAgICAgKi9cbiAgICBzZXRIVE1MOiBmdW5jdGlvbihodG1sKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgICAgICAgdmFyIHRlbXAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib2R5JyksIGNoaWxkO1xuICAgICAgICB0ZW1wLmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjaGlsZCA9IHRlbXAuZmlyc3RDaGlsZDtcbiAgICAgICAgICAgIGlmICghY2hpbGQpIGJyZWFrO1xuICAgICAgICAgICAgdGhpcy5fY29udGVudC5hcHBlbmRDaGlsZChjaGlsZCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVDb250ZW50KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lciA9IERPTS5jcmVhdGUoJ2RpdicsICdtYXBib3hnbC1wb3B1cCcsIHRoaXMuX21hcC5nZXRDb250YWluZXIoKSk7XG5cbiAgICAgICAgICAgIHRoaXMuX3RpcCAgICAgPSBET00uY3JlYXRlKCdkaXYnLCAnbWFwYm94Z2wtcG9wdXAtdGlwJywgICAgIHRoaXMuX2NvbnRhaW5lcik7XG4gICAgICAgICAgICB0aGlzLl93cmFwcGVyID0gRE9NLmNyZWF0ZSgnZGl2JywgJ21hcGJveGdsLXBvcHVwLWNvbnRlbnQnLCB0aGlzLl9jb250YWluZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNsb3NlQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24gPSBET00uY3JlYXRlKCdidXR0b24nLCAnbWFwYm94Z2wtcG9wdXAtY2xvc2UtYnV0dG9uJywgdGhpcy5fd3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uaW5uZXJIVE1MID0gJyYjMjE1Oyc7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrQ2xvc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGVudCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlQ29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fY29udGVudCB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fd3JhcHBlcjtcblxuICAgICAgICB3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICAgICAgICAgIG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGhpcy5fY2xvc2VCdXR0b24pO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2xhdExuZyB8fCAhdGhpcy5fY29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciBwb3MgPSB0aGlzLl9tYXAucHJvamVjdCh0aGlzLl9sYXRMbmcpLnJvdW5kKCksXG4gICAgICAgICAgICBhbmNob3IgPSB0aGlzLm9wdGlvbnMuYW5jaG9yO1xuXG4gICAgICAgIGlmICghYW5jaG9yKSB7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5fY29udGFpbmVyLm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgaWYgKHBvcy55IDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gWyd0b3AnXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9zLnkgPiB0aGlzLl9tYXAudHJhbnNmb3JtLmhlaWdodCAtIGhlaWdodCkge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFsnYm90dG9tJ107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuY2hvciA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocG9zLnggPCB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgnbGVmdCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwb3MueCA+IHRoaXMuX21hcC50cmFuc2Zvcm0ud2lkdGggLSB3aWR0aCAvIDIpIHtcbiAgICAgICAgICAgICAgICBhbmNob3IucHVzaCgncmlnaHQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFuY2hvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBhbmNob3IgPSAnYm90dG9tJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5jaG9yID0gYW5jaG9yLmpvaW4oJy0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFuY2hvciA9IGFuY2hvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhbmNob3JUcmFuc2xhdGUgPSB7XG4gICAgICAgICAgICAndG9wJzogJ3RyYW5zbGF0ZSgtNTAlLDApJyxcbiAgICAgICAgICAgICd0b3AtbGVmdCc6ICd0cmFuc2xhdGUoMCwwKScsXG4gICAgICAgICAgICAndG9wLXJpZ2h0JzogJ3RyYW5zbGF0ZSgtMTAwJSwwKScsXG4gICAgICAgICAgICAnYm90dG9tJzogJ3RyYW5zbGF0ZSgtNTAlLC0xMDAlKScsXG4gICAgICAgICAgICAnYm90dG9tLWxlZnQnOiAndHJhbnNsYXRlKDAsLTEwMCUpJyxcbiAgICAgICAgICAgICdib3R0b20tcmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC0xMDAlKScsXG4gICAgICAgICAgICAnbGVmdCc6ICd0cmFuc2xhdGUoMCwtNTAlKScsXG4gICAgICAgICAgICAncmlnaHQnOiAndHJhbnNsYXRlKC0xMDAlLC01MCUpJ1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjbGFzc0xpc3QgPSB0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0O1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gYW5jaG9yVHJhbnNsYXRlKSB7XG4gICAgICAgICAgICBjbGFzc0xpc3QucmVtb3ZlKCdtYXBib3hnbC1wb3B1cC1hbmNob3ItJyArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xhc3NMaXN0LmFkZCgnbWFwYm94Z2wtcG9wdXAtYW5jaG9yLScgKyBhbmNob3IpO1xuXG4gICAgICAgIERPTS5zZXRUcmFuc2Zvcm0odGhpcy5fY29udGFpbmVyLCBhbmNob3JUcmFuc2xhdGVbYW5jaG9yXSArICcgdHJhbnNsYXRlKCcgKyBwb3MueCArICdweCwnICsgcG9zLnkgKyAncHgpJyk7XG4gICAgfSxcblxuICAgIF9vbkNsaWNrQ2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFjdG9yO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHRoZSBbQWN0b3IgZGVzaWduIHBhdHRlcm5dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWN0b3JfbW9kZWwpXG4gKiB0aGF0IG1haW50YWlucyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYXN5bmNocm9ub3VzIHRhc2tzIGFuZCB0aGUgb2JqZWN0c1xuICogdGhhdCBzcGluIHRoZW0gb2ZmIC0gaW4gdGhpcyBjYXNlLCB0YXNrcyBsaWtlIHBhcnNpbmcgcGFydHMgb2Ygc3R5bGVzLFxuICogb3duZWQgYnkgdGhlIHN0eWxlc1xuICpcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSB0YXJnZXRcbiAqIEBwYXJhbSB7V2ViV29ya2VyfSBwYXJlbnRcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIEFjdG9yKHRhcmdldCwgcGFyZW50KSB7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5jYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLmNhbGxiYWNrSUQgPSAwO1xuICAgIHRoaXMucmVjZWl2ZSA9IHRoaXMucmVjZWl2ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0aGlzLnJlY2VpdmUsIGZhbHNlKTtcbn1cblxuQWN0b3IucHJvdG90eXBlLnJlY2VpdmUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG4gICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGEsXG4gICAgICAgIGNhbGxiYWNrO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJzxyZXNwb25zZT4nKSB7XG4gICAgICAgIGNhbGxiYWNrID0gdGhpcy5jYWxsYmFja3NbZGF0YS5pZF07XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tkYXRhLmlkXTtcbiAgICAgICAgY2FsbGJhY2soZGF0YS5lcnJvciB8fCBudWxsLCBkYXRhLmRhdGEpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEuaWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBpZCA9IGRhdGEuaWQ7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhLCBmdW5jdGlvbihlcnIsIGRhdGEsIGJ1ZmZlcnMpIHtcbiAgICAgICAgICAgIHRoaXMucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICc8cmVzcG9uc2U+JyxcbiAgICAgICAgICAgICAgICBpZDogU3RyaW5nKGlkKSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyID8gU3RyaW5nKGVycikgOiBudWxsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGFcbiAgICAgICAgICAgIH0sIGJ1ZmZlcnMpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50W2RhdGEudHlwZV0oZGF0YS5kYXRhKTtcbiAgICB9XG59O1xuXG5BY3Rvci5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCBidWZmZXJzKSB7XG4gICAgdmFyIGlkID0gbnVsbDtcbiAgICBpZiAoY2FsbGJhY2spIHRoaXMuY2FsbGJhY2tzW2lkID0gdGhpcy5jYWxsYmFja0lEKytdID0gY2FsbGJhY2s7XG4gICAgdGhpcy5wb3N0TWVzc2FnZSh7IHR5cGU6IHR5cGUsIGlkOiBTdHJpbmcoaWQpLCBkYXRhOiBkYXRhIH0sIGJ1ZmZlcnMpO1xufTtcblxuLyoqXG4gKiBXcmFwcGVkIHBvc3RNZXNzYWdlIEFQSSB0aGF0IGFic3RyYWN0cyBhcm91bmQgSUUncyBsYWNrIG9mXG4gKiBgdHJhbnNmZXJMaXN0YCBzdXBwb3J0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmZXJMaXN0XG4gKi9cbkFjdG9yLnByb3RvdHlwZS5wb3N0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCkge1xuICAgIHRyeSB7XG4gICAgICAgIHRoaXMudGFyZ2V0LnBvc3RNZXNzYWdlKG1lc3NhZ2UsIHRyYW5zZmVyTGlzdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLnRhcmdldC5wb3N0TWVzc2FnZShtZXNzYWdlKTsgLy8gTm8gc3VwcG9ydCBmb3IgdHJhbnNmZXJMaXN0IG9uIElFXG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5nZXRKU09OID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICB4aHIub3BlbignR0VUJywgdXJsLCB0cnVlKTtcbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgY2FsbGJhY2soZSk7XG4gICAgfTtcbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh4aHIuc3RhdHVzID49IDIwMCAmJiB4aHIuc3RhdHVzIDwgMzAwICYmIHhoci5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0QXJyYXlCdWZmZXIgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpO1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oZSkge1xuICAgICAgICBjYWxsYmFjayhlKTtcbiAgICB9O1xuICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCAzMDAgJiYgeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCB4aHIucmVzcG9uc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2sobmV3IEVycm9yKHhoci5zdGF0dXNUZXh0KSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHhoci5zZW5kKCk7XG4gICAgcmV0dXJuIHhocjtcbn07XG5cbmV4cG9ydHMuZ2V0SW1hZ2UgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgIGltZy5jcm9zc09yaWdpbiA9ICdBbm9ueW1vdXMnO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgaW1nKTtcbiAgICB9O1xuICAgIGltZy5zcmMgPSB1cmw7XG4gICAgaW1nLmdldERhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBpbWcud2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWcuaGVpZ2h0O1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIDAsIDApO1xuICAgICAgICByZXR1cm4gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW1nLndpZHRoLCBpbWcuaGVpZ2h0KS5kYXRhO1xuICAgIH07XG4gICAgcmV0dXJuIGltZztcbn07XG5cbmV4cG9ydHMuZ2V0VmlkZW8gPSBmdW5jdGlvbih1cmxzLCBjYWxsYmFjaykge1xuICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgdmlkZW8uY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICB2aWRlby5vbmxvYWRzdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCB2aWRlbyk7XG4gICAgfTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzb3VyY2UnKTtcbiAgICAgICAgcy5zcmMgPSB1cmxzW2ldO1xuICAgICAgICB2aWRlby5hcHBlbmRDaGlsZChzKTtcbiAgICB9XG4gICAgdmlkZW8uZ2V0RGF0YSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdmlkZW87IH07XG4gICAgcmV0dXJuIHZpZGVvO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENhbnZhcyA9IHJlcXVpcmUoJy4vY2FudmFzJyk7XG5cbnZhciBmcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5mcmFtZSA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgcmV0dXJuIGZyYW1lKGZuKTtcbn07XG5cbnZhciBjYW5jZWwgPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNDYW5jZWxBbmltYXRpb25GcmFtZTtcblxuZXhwb3J0cy5jYW5jZWxGcmFtZSA9IGZ1bmN0aW9uKGlkKSB7XG4gICAgY2FuY2VsKGlkKTtcbn07XG5cbmV4cG9ydHMudGltZWQgPSBmdW5jdGlvbiAoZm4sIGR1ciwgY3R4KSB7XG4gICAgaWYgKCFkdXIpIHtcbiAgICAgICAgZm4uY2FsbChjdHgsIDEpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYWJvcnQgPSBmYWxzZSxcbiAgICAgICAgc3RhcnQgPSB3aW5kb3cucGVyZm9ybWFuY2UgPyB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdygpO1xuXG4gICAgZnVuY3Rpb24gdGljayhub3cpIHtcbiAgICAgICAgaWYgKGFib3J0KSByZXR1cm47XG4gICAgICAgIGlmICghd2luZG93LnBlcmZvcm1hbmNlKSBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIGlmIChub3cgPj0gc3RhcnQgKyBkdXIpIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZuLmNhbGwoY3R4LCAobm93IC0gc3RhcnQpIC8gZHVyKTtcbiAgICAgICAgICAgIGV4cG9ydHMuZnJhbWUodGljayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBleHBvcnRzLmZyYW1lKHRpY2spO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyBhYm9ydCA9IHRydWU7IH07XG59O1xuXG4vKipcbiAqIFRlc3Qgd2hldGhlciB0aGUgYmFzaWMgSmF2YVNjcmlwdCBhbmQgRE9NIGZlYXR1cmVzIHJlcXVpcmVkIGZvciBNYXBib3ggR0wgYXJlIHByZXNlbnQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0PWZhbHNlXSBJZiBgdHJ1ZWAsIG1hcCBjcmVhdGlvbiB3aWxsIGZhaWwgaWYgdGhlIGltcGxlbWVudGF0aW9uIGRldGVybWluZXMgdGhhdCB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGNyZWF0ZWQgV2ViR0wgY29udGV4dCB3b3VsZCBiZSBkcmFtYXRpY2FsbHkgbG93ZXIgdGhhbiBleHBlY3RlZC5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiBNYXBib3ggR0wgc2hvdWxkIGJlIGV4cGVjdGVkIHRvIHdvcmssIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cbmV4cG9ydHMuc3VwcG9ydGVkID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gICAgdmFyIHN1cHBvcnRzID0gW1xuXG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7IH0sXG5cbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnOyB9LFxuXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShBcnJheS5wcm90b3R5cGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZXZlcnkgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuZmlsdGVyICYmXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2ggJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZiAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5tYXAgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc29tZSAmJlxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2UgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucmVkdWNlUmlnaHQgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAhIShGdW5jdGlvbi5wcm90b3R5cGUgJiYgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpICYmXG4gICAgICAgICAgICAgICAgISEoT2JqZWN0LmtleXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmNyZWF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmlzU2VhbGVkICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5pc0Zyb3plbiAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuaXNFeHRlbnNpYmxlICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5zZWFsICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5mcmVlemUgJiZcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAnSlNPTicgaW4gd2luZG93ICYmICdwYXJzZScgaW4gSlNPTiAmJiAnc3RyaW5naWZ5JyBpbiBKU09OO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDYW52YXMoKS5zdXBwb3J0c1dlYkdMQ29udGV4dCgob3B0aW9ucyAmJiBvcHRpb25zLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpIHx8IGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuICdXb3JrZXInIGluIHdpbmRvdzsgfVxuICAgIF07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1cHBvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghc3VwcG9ydHNbaV0oKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydHMuaGFyZHdhcmVDb25jdXJyZW5jeSA9IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5IHx8IDg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGV2aWNlUGl4ZWxSYXRpbycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW87IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYW52YXM7XG5cbmZ1bmN0aW9uIENhbnZhcyhwYXJlbnQsIGNvbnRhaW5lcikge1xuICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG5cbiAgICBpZiAocGFyZW50ICYmIGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgIHRoaXMuY2FudmFzLmNsYXNzTGlzdC5hZGQoJ21hcGJveGdsLWNhbnZhcycpO1xuICAgICAgICB0aGlzLmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgcGFyZW50Ll9jb250ZXh0TG9zdC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0cmVzdG9yZWQnLCBwYXJlbnQuX2NvbnRleHRSZXN0b3JlZC5iaW5kKHBhcmVudCksIGZhbHNlKTtcbiAgICAgICAgdGhpcy5jYW52YXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIDApO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgIH1cbn1cblxuQ2FudmFzLnByb3RvdHlwZS5yZXNpemUgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgLy8gUmVxdWVzdCB0aGUgcmVxdWlyZWQgY2FudmFzIHNpemUgdGFraW5nIHRoZSBwaXhlbHJhdGlvIGludG8gYWNjb3VudC5cbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHBpeGVsUmF0aW8gKiB3aWR0aDtcbiAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBwaXhlbFJhdGlvICogaGVpZ2h0O1xuXG4gICAgLy8gTWFpbnRhaW4gdGhlIHNhbWUgY2FudmFzIHNpemUsIHBvdGVudGlhbGx5IGRvd25zY2FsaW5nIGl0IGZvciBIaURQSSBkaXNwbGF5c1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICAgIHRoaXMuY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG59O1xuXG52YXIgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyA9IHtcbiAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgIGFscGhhOiB0cnVlLFxuICAgIHN0ZW5jaWw6IHRydWUsXG4gICAgZGVwdGg6IGZhbHNlXG59O1xuXG5DYW52YXMucHJvdG90eXBlLmdldFdlYkdMQ29udGV4dCA9IGZ1bmN0aW9uKGF0dHJpYnV0ZXMpIHtcbiAgICBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe30sIGF0dHJpYnV0ZXMsIHJlcXVpcmVkQ29udGV4dEF0dHJpYnV0ZXMpO1xuXG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldENvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG59O1xuXG5DYW52YXMucHJvdG90eXBlLnN1cHBvcnRzV2ViR0xDb250ZXh0ID0gZnVuY3Rpb24oZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0gdXRpbC5leHRlbmQoe1xuICAgICAgICBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0OiBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0XG4gICAgfSwgcmVxdWlyZWRDb250ZXh0QXR0cmlidXRlcyk7XG5cbiAgICBpZiAoJ3Byb2JhYmx5U3VwcG9ydHNDb250ZXh0JyBpbiB0aGlzLmNhbnZhcykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXMucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0KCdleHBlcmltZW50YWwtd2ViZ2wnLCBhdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2UgaWYgKCdzdXBwb3J0c0NvbnRleHQnIGluIHRoaXMuY2FudmFzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhcy5zdXBwb3J0c0NvbnRleHQoJ3dlYmdsJywgYXR0cmlidXRlcykgfHxcbiAgICAgICAgICAgIHRoaXMuY2FudmFzLnN1cHBvcnRzQ29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuICEhd2luZG93LldlYkdMUmVuZGVyaW5nQ29udGV4dCAmJiAhIXRoaXMuZ2V0V2ViR0xDb250ZXh0KGZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQpO1xufTtcblxuQ2FudmFzLnByb3RvdHlwZS5nZXRFbGVtZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFjdG9yID0gcmVxdWlyZSgnLi4vYWN0b3InKTtcbnZhciBXZWJXb3JraWZ5ID0gcmVxdWlyZSgnd2Vid29ya2lmeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERpc3BhdGNoZXI7XG5cbmZ1bmN0aW9uIERpc3BhdGNoZXIobGVuZ3RoLCBwYXJlbnQpIHtcbiAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIHRoaXMuY3VycmVudEFjdG9yID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB3b3JrZXIgPSBuZXcgV2ViV29ya2lmeShyZXF1aXJlKCcuLi8uLi9zb3VyY2Uvd29ya2VyJykpO1xuICAgICAgICB2YXIgYWN0b3IgPSBuZXcgQWN0b3Iod29ya2VyLCBwYXJlbnQpO1xuICAgICAgICBhY3Rvci5uYW1lID0gXCJXb3JrZXIgXCIgKyBpO1xuICAgICAgICB0aGlzLmFjdG9ycy5wdXNoKGFjdG9yKTtcbiAgICB9XG59XG5cbkRpc3BhdGNoZXIucHJvdG90eXBlID0ge1xuICAgIGJyb2FkY2FzdDogZnVuY3Rpb24odHlwZSwgZGF0YSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmFjdG9yc1tpXS5zZW5kKHR5cGUsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNlbmQ6IGZ1bmN0aW9uKHR5cGUsIGRhdGEsIGNhbGxiYWNrLCB0YXJnZXRJRCwgYnVmZmVycykge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldElEICE9PSAnbnVtYmVyJyB8fCBpc05hTih0YXJnZXRJRCkpIHtcbiAgICAgICAgICAgIC8vIFVzZSByb3VuZCByb2JpbiB0byBzZW5kIHJlcXVlc3RzIHRvIHdlYiB3b3JrZXJzLlxuICAgICAgICAgICAgdGFyZ2V0SUQgPSB0aGlzLmN1cnJlbnRBY3RvciA9ICh0aGlzLmN1cnJlbnRBY3RvciArIDEpICUgdGhpcy5hY3RvcnMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hY3RvcnNbdGFyZ2V0SURdLnNlbmQodHlwZSwgZGF0YSwgY2FsbGJhY2ssIGJ1ZmZlcnMpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0SUQ7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuYWN0b3JzW2ldLnRhcmdldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdG9ycyA9IFtdO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24gKHRhZ05hbWUsIGNsYXNzTmFtZSwgY29udGFpbmVyKSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbiAgICBpZiAoY2xhc3NOYW1lKSBlbC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgaWYgKGNvbnRhaW5lcikgY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcbiAgICByZXR1cm4gZWw7XG59O1xuXG52YXIgZG9jU3R5bGUgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU7XG5cbmZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocHJvcHNbaV0gaW4gZG9jU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBwcm9wc1tpXTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxudmFyIHNlbGVjdFByb3AgPSB0ZXN0UHJvcChbJ3VzZXJTZWxlY3QnLCAnTW96VXNlclNlbGVjdCcsICdXZWJraXRVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKSxcbiAgICB1c2VyU2VsZWN0O1xuZXhwb3J0cy5kaXNhYmxlRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc2VsZWN0UHJvcCkge1xuICAgICAgICB1c2VyU2VsZWN0ID0gZG9jU3R5bGVbc2VsZWN0UHJvcF07XG4gICAgICAgIGRvY1N0eWxlW3NlbGVjdFByb3BdID0gJ25vbmUnO1xuICAgIH1cbn07XG5leHBvcnRzLmVuYWJsZURyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGVjdFByb3ApIHtcbiAgICAgICAgZG9jU3R5bGVbc2VsZWN0UHJvcF0gPSB1c2VyU2VsZWN0O1xuICAgIH1cbn07XG5cbnZhciB0cmFuc2Zvcm1Qcm9wID0gdGVzdFByb3AoWyd0cmFuc2Zvcm0nLCAnV2Via2l0VHJhbnNmb3JtJ10pO1xuZXhwb3J0cy5zZXRUcmFuc2Zvcm0gPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBlbC5zdHlsZVt0cmFuc2Zvcm1Qcm9wXSA9IHZhbHVlO1xufTtcblxuLy8gU3VwcHJlc3MgdGhlIG5leHQgY2xpY2ssIGJ1dCBvbmx5IGlmIGl0J3MgaW1tZWRpYXRlLlxuZnVuY3Rpb24gc3VwcHJlc3NDbGljayhlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG59XG5leHBvcnRzLnN1cHByZXNzQ2xpY2sgPSBmdW5jdGlvbigpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBzdXBwcmVzc0NsaWNrLCB0cnVlKTtcbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgc3VwcHJlc3NDbGljaywgdHJ1ZSk7XG4gICAgfSwgMCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIVFRQX1VSTDogJ2h0dHA6Ly9hLnRpbGVzLm1hcGJveC5jb20nLFxuICAgIEhUVFBTX1VSTDogJ2h0dHBzOi8vYS50aWxlcy5tYXBib3guY29tJyxcbiAgICBGT1JDRV9IVFRQUzogdHJ1ZSxcbiAgICBSRVFVSVJFX0FDQ0VTU19UT0tFTjogdHJ1ZVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLyoqXG4gKiBNZXRob2RzIG1peGVkIGluIHRvIG90aGVyIGNsYXNzZXMgZm9yIGV2ZW50IGNhcGFiaWxpdGllcy5cbiAqIEBtaXhpbiBFdmVudGVkXG4gKi9cbnZhciBFdmVudGVkID0ge1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGEgc3BlY2lmaWVkIGV2ZW50IHdpdGggYSBsaXN0ZW5lciBmdW5jdGlvbiB0aGUgbGF0dGVyIGdldHMgdGhlIGRhdGEgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCB0byBgZmlyZWAgYW5kIGFkZGl0aW9uYWxseSBgdGFyZ2V0YCBhbmQgYHR5cGVgIHByb3BlcnRpZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbjogZnVuY3Rpb24odHlwZSwgZm4pIHtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSB0aGlzLl9ldmVudHNbdHlwZV0gfHwgW107XG4gICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGZuKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGEgZXZlbnQgbGlzdGVuZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBbdHlwZV0gRXZlbnQgdHlwZS4gSWYgbm9uZSBpcyBzcGVjaWZpZWQsIHJlbW92ZSBhbGwgbGlzdGVuZXJzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2xpc3RlbmVyXSBGdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWQuIElmIG5vbmUgaXMgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgYXJlIHJlbW92ZWRcbiAgICAgKi9cbiAgICBvZmY6IGZ1bmN0aW9uKHR5cGUsIGZuKSB7XG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgICAgLy8gY2xlYXIgYWxsIGxpc3RlbmVycyBpZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMubGlzdGVucyh0eXBlKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGZuKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gdGhpcy5fZXZlbnRzW3R5cGVdLmluZGV4T2YoZm4pO1xuICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbCBhIGZ1bmN0aW9uIG9uY2Ugd2hlbiBhbiBldmVudCBoYXMgZmlyZWRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIEV2ZW50IHR5cGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgRnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uY2Ugd2hlbiB0aGUgZXZlbnQgaXMgZmlyZWRcbiAgICAgKi9cbiAgICBvbmNlOiBmdW5jdGlvbih0eXBlLCBmbikge1xuICAgICAgICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMub2ZmKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICAgICAgZm4uY2FsbCh0aGlzLCBkYXRhKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLm9uKHR5cGUsIHdyYXBwZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRmlyZSBldmVudCBvZiBhIGdpdmVuIHN0cmluZyB0eXBlIHdpdGggdGhlIGdpdmVuIGRhdGEgb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXZlbnQgbmFtZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV0gT3B0aW9uYWwgZGF0YSBwYXNzZWQgZG93biB0byB0aGUgZXZlbnQgb2JqZWN0XG4gICAgICogQHJldHVybnMge0Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgb2JqZWN0IGxpc3RlbnMgdG8gYW4gZXZlbnQgb2YgYSBwYXJ0aWN1bGFyIHR5cGVcbiAgICAgKi9cbiAgICBmaXJlOiBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0ZW5zKHR5cGUpKSByZXR1cm4gdGhpcztcblxuICAgICAgICBkYXRhID0gdXRpbC5leHRlbmQoe30sIGRhdGEpO1xuICAgICAgICB1dGlsLmV4dGVuZChkYXRhLCB7dHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzfSk7XG5cbiAgICAgICAgLy8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmNhbGwodGhpcywgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYW4gZXZlbnQgaXMgcmVnaXN0ZXJlZCB0byBhIHR5cGVcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBvYmplY3QgbGlzdGVucyB0byBhbiBldmVudCBvZiBhIHBhcnRpY3VsYXIgdHlwZVxuICAgICAqL1xuICAgIGxpc3RlbnM6IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuICEhKHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbdHlwZV0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRlZDtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBHbHlwaHM7XG5cbmZ1bmN0aW9uIEdseXBocyhwYmYsIGVuZCkge1xuICAgIHRoaXMuc3RhY2tzID0gcGJmLnJlYWRGaWVsZHMocmVhZEZvbnRzdGFja3MsIFtdLCBlbmQpO1xufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrcyh0YWcsIHN0YWNrcywgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkge1xuICAgICAgICB2YXIgZm9udHN0YWNrID0gcGJmLnJlYWRNZXNzYWdlKHJlYWRGb250c3RhY2ssIHtnbHlwaHM6IHt9fSk7XG4gICAgICAgIHN0YWNrcy5wdXNoKGZvbnRzdGFjayk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkRm9udHN0YWNrKHRhZywgZm9udHN0YWNrLCBwYmYpIHtcbiAgICBpZiAodGFnID09PSAxKSBmb250c3RhY2submFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSAyKSBmb250c3RhY2sucmFuZ2UgPSBwYmYucmVhZFN0cmluZygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykge1xuICAgICAgICB2YXIgZ2x5cGggPSBwYmYucmVhZE1lc3NhZ2UocmVhZEdseXBoLCB7fSk7XG4gICAgICAgIGZvbnRzdGFjay5nbHlwaHNbZ2x5cGguaWRdID0gZ2x5cGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWFkR2x5cGgodGFnLCBnbHlwaCwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMSkgZ2x5cGguaWQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgZ2x5cGguYml0bWFwID0gcGJmLnJlYWRCeXRlcygpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMykgZ2x5cGgud2lkdGggPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgZ2x5cGguaGVpZ2h0ID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDUpIGdseXBoLmxlZnQgPSBwYmYucmVhZFNWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT09IDYpIGdseXBoLnRvcCA9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNykgZ2x5cGguYWR2YW5jZSA9IHBiZi5yZWFkVmFyaW50KCk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGU7XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKGEsIGIsIHQpIHtcbiAgICByZXR1cm4gKGEgKiAoMSAtIHQpKSArIChiICogdCk7XG59XG5cbmludGVycG9sYXRlLm51bWJlciA9IGludGVycG9sYXRlO1xuXG5pbnRlcnBvbGF0ZS52ZWMyID0gZnVuY3Rpb24oZnJvbSwgdG8sIHQpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzBdLCB0b1swXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMV0sIHRvWzFdLCB0KVxuICAgIF07XG59O1xuXG4vKlxuICogSW50ZXJwb2xhdGUgYmV0d2VlbiB0d28gY29sb3JzIGdpdmVuIGFzIDQtZWxlbWVudCBhcnJheXMuXG4gKlxuICogQHBhcmFtIHtDb2xvcn0gZnJvbVxuICogQHBhcmFtIHtDb2xvcn0gdG9cbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gZmFjdG9yIGJldHdlZW4gMCBhbmQgMVxuICogQHJldHVybnMge0NvbG9yfSBpbnRlcnBvbGF0ZWQgY29sb3JcbiAqL1xuaW50ZXJwb2xhdGUuY29sb3IgPSBmdW5jdGlvbihmcm9tLCB0bywgdCkge1xuICAgIHJldHVybiBbXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bMF0sIHRvWzBdLCB0KSxcbiAgICAgICAgaW50ZXJwb2xhdGUoZnJvbVsxXSwgdG9bMV0sIHQpLFxuICAgICAgICBpbnRlcnBvbGF0ZShmcm9tWzJdLCB0b1syXSwgdCksXG4gICAgICAgIGludGVycG9sYXRlKGZyb21bM10sIHRvWzNdLCB0KVxuICAgIF07XG59O1xuXG5pbnRlcnBvbGF0ZS5hcnJheSA9IGZ1bmN0aW9uKGZyb20sIHRvLCB0KSB7XG4gICAgcmV0dXJuIGZyb20ubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlKGQsIHRvW2ldLCB0KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIGJyb3dzZXIgPSByZXF1aXJlKCcuL2Jyb3dzZXInKTtcblxuZnVuY3Rpb24gbm9ybWFsaXplVVJMKHVybCwgcGF0aFByZWZpeCwgYWNjZXNzVG9rZW4pIHtcbiAgICBhY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuIHx8IGNvbmZpZy5BQ0NFU1NfVE9LRU47XG5cbiAgICBpZiAoIWFjY2Vzc1Rva2VuICYmIGNvbmZpZy5SRVFVSVJFX0FDQ0VTU19UT0tFTikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FuIEFQSSBhY2Nlc3MgdG9rZW4gaXMgcmVxdWlyZWQgdG8gdXNlIE1hcGJveCBHTC4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vZGV2ZWxvcGVycy9hcGkvI2FjY2Vzcy10b2tlbnMnKTtcbiAgICB9XG5cbiAgICB2YXIgaHR0cHMgPSBjb25maWcuRk9SQ0VfSFRUUFMgfHxcbiAgICAgICAgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonKTtcblxuICAgIHVybCA9IHVybC5yZXBsYWNlKC9ebWFwYm94OlxcL1xcLy8sIChodHRwcyA/IGNvbmZpZy5IVFRQU19VUkwgOiBjb25maWcuSFRUUF9VUkwpICsgcGF0aFByZWZpeCk7XG4gICAgdXJsICs9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyZhY2Nlc3NfdG9rZW49JyA6ICc/YWNjZXNzX3Rva2VuPSc7XG5cbiAgICBpZiAoY29uZmlnLlJFUVVJUkVfQUNDRVNTX1RPS0VOKSB7XG4gICAgICAgIGlmIChhY2Nlc3NUb2tlblswXSA9PT0gJ3MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VzZSBhIHB1YmxpYyBhY2Nlc3MgdG9rZW4gKHBrLiopIHdpdGggTWFwYm94IEdMIEpTLCBub3QgYSBzZWNyZXQgYWNjZXNzIHRva2VuIChzay4qKS4gJyArXG4gICAgICAgICAgICAgICAgJ1NlZSBodHRwczovL3d3dy5tYXBib3guY29tL2RldmVsb3BlcnMvYXBpLyNhY2Nlc3MtdG9rZW5zJyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cmwgKz0gYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybDtcbn1cblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU3R5bGVVUkwgPSBmdW5jdGlvbih1cmwsIGFjY2Vzc1Rva2VuKSB7XG4gICAgdmFyIHVzZXIgPSB1cmwubWF0Y2goL15tYXBib3g6XFwvXFwvKFteLl0rKS8pO1xuICAgIGlmICghdXNlcilcbiAgICAgICAgcmV0dXJuIHVybDtcblxuICAgIHJldHVybiBub3JtYWxpemVVUkwodXJsLCAnL3N0eWxlcy92MS8nICsgdXNlclsxXSArICcvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplU291cmNlVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgdXJsID0gbm9ybWFsaXplVVJMKHVybCArICcuanNvbicsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xuXG4gICAgLy8gVGlsZUpTT04gcmVxdWVzdHMgbmVlZCBhIHNlY3VyZSBmbGFnIGFwcGVuZGVkIHRvIHRoZWlyIFVSTHMgc29cbiAgICAvLyB0aGF0IHRoZSBzZXJ2ZXIga25vd3MgdG8gc2VuZCBTU0wtaWZpZWQgcmVzb3VyY2UgcmVmZXJlbmNlcy5cbiAgICBpZiAodXJsLmluZGV4T2YoJ2h0dHBzJykgPT09IDApXG4gICAgICAgIHVybCArPSAnJnNlY3VyZSc7XG5cbiAgICByZXR1cm4gdXJsO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplR2x5cGhzVVJMID0gZnVuY3Rpb24odXJsLCBhY2Nlc3NUb2tlbikge1xuICAgIGlmICghdXJsLm1hdGNoKC9ebWFwYm94OlxcL1xcLy8pKVxuICAgICAgICByZXR1cm4gdXJsO1xuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZVVSTCh1cmwsICcvdjQvJywgYWNjZXNzVG9rZW4pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubm9ybWFsaXplVGlsZVVSTCA9IGZ1bmN0aW9uKHVybCwgc291cmNlVXJsKSB7XG4gICAgaWYgKCFzb3VyY2VVcmwgfHwgIXNvdXJjZVVybC5tYXRjaCgvXm1hcGJveDpcXC9cXC8vKSlcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICByZXR1cm4gdXJsLnJlcGxhY2UoL1xcLigoPzpwbmd8anBnKVxcZCopKD89JHxcXD8pLywgYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvID49IDIgPyAnQDJ4LiQxJyA6ICcuJDEnKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qXG4gKiBBIFttb3N0LXJlY2VudGx5LXVzZWQgY2FjaGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FjaGVfYWxnb3JpdGhtcylcbiAqIHdpdGggaGFzaCBsb29rdXAgbWFkZSBwb3NzaWJsZSBieSBrZWVwaW5nIGEgbGlzdCBvZiBrZXlzIGluIHBhcmFsbGVsIHRvXG4gKiBhbiBhcnJheSBvZiBkaWN0aW9uYXJ5IG9mIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXggbnVtYmVyIG9mIHBlcm1pdHRlZCB2YWx1ZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVtb3ZlIGNhbGxiYWNrIGNhbGxlZCB3aXRoIGl0ZW1zIHdoZW4gdGhleSBleHBpcmVcbiAqIEBwcml2YXRlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gTVJVQ2FjaGU7XG5mdW5jdGlvbiBNUlVDYWNoZShtYXgsIG9uUmVtb3ZlKSB7XG4gICAgdGhpcy5tYXggPSBtYXg7XG4gICAgdGhpcy5vblJlbW92ZSA9IG9uUmVtb3ZlO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cblxuLyoqXG4gKiBDbGVhciB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7TVJVQ2FjaGV9IHRoaXMgY2FjaGVcbiAqL1xuTVJVQ2FjaGUucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMubGlzdCkge1xuICAgICAgICB0aGlzLm9uUmVtb3ZlKHRoaXMubGlzdFtrZXldKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpc3QgPSB7fTtcbiAgICB0aGlzLm9yZGVyID0gW107XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBBZGQgYSBrZXksIHZhbHVlIGNvbWJpbmF0aW9uIHRvIHRoZSBjYWNoZSwgdHJpbW1pbmcgaXRzIHNpemUgaWYgdGhpcyBwdXNoZXNcbiAqIGl0IG92ZXIgbWF4IGxlbmd0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IGxvb2t1cCBrZXkgZm9yIHRoZSBpdGVtXG4gKiBAcGFyYW0geyp9IGRhdGEgYW55IHZhbHVlXG4gKlxuICogQHJldHVybnMge01SVUNhY2hlfSB0aGlzIGNhY2hlXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB0aGlzLmxpc3Rba2V5XSA9IGRhdGE7XG4gICAgdGhpcy5vcmRlci5wdXNoKGtleSk7XG5cbiAgICBpZiAodGhpcy5vcmRlci5sZW5ndGggPiB0aGlzLm1heCkge1xuICAgICAgICB2YXIgcmVtb3ZlZERhdGEgPSB0aGlzLmdldCh0aGlzLm9yZGVyWzBdKTtcbiAgICAgICAgaWYgKHJlbW92ZWREYXRhKSB0aGlzLm9uUmVtb3ZlKHJlbW92ZWREYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYGtleWAgaXMgcHJlc2VudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBiZSBsb29rZWQtdXBcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIHRoZSBjYWNoZSBoYXMgdGhpcyB2YWx1ZVxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmxpc3Q7XG59O1xuXG4vKlxuICogTGlzdCBhbGwga2V5cyBpbiB0aGUgY2FjaGVcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gYW4gYXJyYXkgb2Yga2V5cyBpbiB0aGlzIGNhY2hlLlxuICovXG5NUlVDYWNoZS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm9yZGVyO1xufTtcblxuLypcbiAqIEdldCB0aGUgdmFsdWUgYXR0YWNoZWQgdG8gYSBzcGVjaWZpYyBrZXkuIElmIHRoZSBrZXkgaXMgbm90IGZvdW5kLFxuICogcmV0dXJucyBgbnVsbGBcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gbG9vayB1cFxuICogQHJldHVybnMgeyp9IHRoZSBkYXRhLCBvciBudWxsIGlmIGl0IGlzbid0IGZvdW5kXG4gKi9cbk1SVUNhY2hlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsgcmV0dXJuIG51bGw7IH1cblxuICAgIHZhciBkYXRhID0gdGhpcy5saXN0W2tleV07XG5cbiAgICBkZWxldGUgdGhpcy5saXN0W2tleV07XG4gICAgdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGtleSksIDEpO1xuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlc29sdmVUb2tlbnM7XG5cbi8qKlxuICogUmVwbGFjZSB0b2tlbnMgaW4gYSBzdHJpbmcgdGVtcGxhdGUgd2l0aCB2YWx1ZXMgaW4gYW4gb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgYSBrZXkvdmFsdWUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9rZW5zIGFuZCByZXBsYWNlbWVudHNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IHRoZSB0ZW1wbGF0ZSBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0ZW1wbGF0ZSB3aXRoIHRva2VucyByZXBsYWNlZFxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVRva2Vucyhwcm9wZXJ0aWVzLCB0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgveyhbXnt9KClcXFtcXF08PiQ9OjsuLF5dKyl9L2csIGZ1bmN0aW9uKG1hdGNoLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSBpbiBwcm9wZXJ0aWVzID8gcHJvcGVydGllc1trZXldIDogJyc7XG4gICAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBVbml0QmV6aWVyID0gcmVxdWlyZSgndW5pdGJlemllcicpO1xuXG4vKipcbiAqIEdpdmVuIGEgdmFsdWUgYHRgIHRoYXQgdmFyaWVzIGJldHdlZW4gMCBhbmQgMSwgcmV0dXJuXG4gKiBhbiBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uIHRoYXQgZWFzZXMgYmV0d2VlbiAwIGFuZCAxIGluIGEgcGxlYXNpbmdcbiAqIGN1YmljIGluLW91dCBmYXNoaW9uLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IGlucHV0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBpbnB1dFxuICovXG5leHBvcnRzLmVhc2VDdWJpY0luT3V0ID0gZnVuY3Rpb24gKHQpIHtcbiAgICBpZiAodCA8PSAwKSByZXR1cm4gMDtcbiAgICBpZiAodCA+PSAxKSByZXR1cm4gMTtcbiAgICB2YXIgdDIgPSB0ICogdCxcbiAgICAgICAgdDMgPSB0MiAqIHQ7XG4gICAgcmV0dXJuIDQgKiAodCA8IDAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAwLjc1KTtcbn07XG5cbi8qKlxuICogR2l2ZW4gZ2l2ZW4gKHgsIHkpLCAoeDEsIHkxKSBjb250cm9sIHBvaW50cyBmb3IgYSBiZXppZXIgY3VydmUsXG4gKiByZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGludGVycG9sYXRlcyBhbG9uZyB0aGF0IGN1cnZlLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMXggY29udHJvbCBwb2ludCAxIHggY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHAxeSBjb250cm9sIHBvaW50IDEgeSBjb29yZGluYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gcDJ4IGNvbnRyb2wgcG9pbnQgMiB4IGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBwMnkgY29udHJvbCBwb2ludCAyIHkgY29vcmRpbmF0ZVxuICogQHJldHVybnMge0Z1bmN0aW9ufSBpbnRlcnBvbGF0b3I6IHJlY2VpdmVzIG51bWJlciB2YWx1ZSwgcmV0dXJuc1xuICogbnVtYmVyIHZhbHVlLlxuICovXG5leHBvcnRzLmJlemllciA9IGZ1bmN0aW9uKHAxeCwgcDF5LCBwMngsIHAyeSkge1xuICAgIHZhciBiZXppZXIgPSBuZXcgVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHJldHVybiBiZXppZXIuc29sdmUodCk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogQSBkZWZhdWx0IGJlemllci1jdXJ2ZSBwb3dlcmVkIGVhc2luZyBmdW5jdGlvbiB3aXRoXG4gKiBjb250cm9sIHBvaW50cyAoMC4yNSwgMC4xKSBhbmQgKDAuMjUsIDEpXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IG91dHB1dFxuICovXG5leHBvcnRzLmVhc2UgPSBleHBvcnRzLmJlemllcigwLjI1LCAwLjEsIDAuMjUsIDEpO1xuXG4vKipcbiAqIEdpdmVuIGEgZm91ci1lbGVtZW50IGFycmF5IG9mIG51bWJlcnMgdGhhdCByZXByZXNlbnRzIGEgY29sb3IgaW5cbiAqIFJHQkEsIHJldHVybiBhIHZlcnNpb24gZm9yIHdoaWNoIHRoZSBSR0IgY29tcG9uZW50cyBhcmUgbXVsdGlwbGllZFxuICogYnkgdGhlIEEgKGFscGhhKSBjb21wb25lbnRcbiAqXG4gKiBAcGFyYW0ge051bWJlcjxBcnJheT59IGMgY29sb3IgYXJyYXlcbiAqIEByZXR1cm5zIHtOdW1iZXI8QXJyYXk+fSBwcmVtdWx0aXBsaWVkIGNvbG9yIGFycmF5XG4gKi9cbmV4cG9ydHMucHJlbXVsdGlwbHkgPSBmdW5jdGlvbiAoYykge1xuICAgIGNbMF0gKj0gY1szXTtcbiAgICBjWzFdICo9IGNbM107XG4gICAgY1syXSAqPSBjWzNdO1xuICAgIHJldHVybiBjO1xufTtcblxuLyoqXG4gKiBjb25zdHJhaW4gbiB0byB0aGUgZ2l2ZW4gcmFuZ2UgdmlhIG1pbiArIG1heFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuIHZhbHVlXG4gKiBAcGFyYW0ge051bWJlcn0gbWluIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4IHRoZSBtYXhpbXVtIHZhbHVlIHRvIGJlIHJldHVybmVkXG4gKiBAcmV0dXJucyB7TnVtYmVyfSB0aGUgY2xhbXBlZCB2YWx1ZVxuICovXG5leHBvcnRzLmNsYW1wID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCBuKSk7XG59O1xuXG4vKlxuICogY29uc3RyYWluIG4gdG8gdGhlIGdpdmVuIHJhbmdlIHZpYSBtb2R1bGFyIGFyaXRobWV0aWNcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcGFyYW0ge051bWJlcn0gbWluXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBjb25zdHJhaW5lZCBudW1iZXJcbiAqL1xuZXhwb3J0cy53cmFwID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4KSB7XG4gICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgcmV0dXJuIG4gPT09IG1heCA/IG4gOiAoKG4gLSBtaW4pICUgZCArIGQpICUgZCArIG1pbjtcbn07XG5cbi8qXG4gKiByZXR1cm4gdGhlIGZpcnN0IG5vbi1udWxsIGFuZCBub24tdW5kZWZpbmVkIGFyZ3VtZW50IHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7Kn0gYXJndW1lbnRcbiAqL1xuZXhwb3J0cy5jb2FsZXNjZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGlmIChhcmcgIT09IG51bGwgJiYgYXJnICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gYXJnO1xuICAgIH1cbn07XG5cbi8qXG4gKiBDYWxsIGFuIGFzeW5jaHJvbm91cyBmdW5jdGlvbiBvbiBhbiBhcnJheSBvZiBhcmd1bWVudHMsXG4gKiBjYWxsaW5nIGBjYWxsYmFja2Agb25jZSBhbGwgY2FsbHMgY29tcGxldGUuXG4gKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyYXkgaW5wdXQgdG8gZWFjaCBjYWxsIG9mIHRoZSBhc3luYyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIGFuIGFzeW5jIGZ1bmN0aW9uIHdpdGggc2lnbmF0dXJlIChkYXRhLCBjYWxsYmFjaylcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgY2FsbGJhY2sgcnVuIGFmdGVyIGFsbCBhc3luYyB3b3JrIGlzIGRvbmUuXG4gKiBjYWxsZWQgd2l0aCBubyBhcmd1bWVudHNcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydHMuYXN5bmNFYWNoID0gZnVuY3Rpb24gKGFycmF5LCBmbiwgY2FsbGJhY2spIHtcbiAgICB2YXIgcmVtYWluaW5nID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChyZW1haW5pbmcgPT09IDApIHJldHVybiBjYWxsYmFjaygpO1xuICAgIGZ1bmN0aW9uIGNoZWNrKCkgeyBpZiAoLS1yZW1haW5pbmcgPT09IDApIGNhbGxiYWNrKCk7IH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSBmbihhcnJheVtpXSwgY2hlY2spO1xufTtcblxuLypcbiAqIENvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUga2V5cyBpbiBvbmUgb2JqZWN0IGFuZCB0aGUga2V5c1xuICogaW4gYW5vdGhlciBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0ga2V5cyBkaWZmZXJlbmNlXG4gKi9cbmV4cG9ydHMua2V5c0RpZmZlcmVuY2UgPSBmdW5jdGlvbiAob2JqLCBvdGhlcikge1xuICAgIHZhciBkaWZmZXJlbmNlID0gW107XG4gICAgZm9yICh2YXIgaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKCEoaSBpbiBvdGhlcikpIHtcbiAgICAgICAgICAgIGRpZmZlcmVuY2UucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGlmZmVyZW5jZTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYSBkZXN0aW5hdGlvbiBvYmplY3QgYW5kIG9wdGlvbmFsbHkgbWFueSBzb3VyY2Ugb2JqZWN0cyxcbiAqIGNvcHkgYWxsIHByb3BlcnRpZXMgZnJvbSB0aGUgc291cmNlIG9iamVjdHMgaW50byB0aGUgZGVzdGluYXRpb24uXG4gKiBUaGUgbGFzdCBzb3VyY2Ugb2JqZWN0IGdpdmVuIG92ZXJyaWRlcyBwcm9wZXJ0aWVzIGZyb20gcHJldmlvdXNcbiAqIHNvdXJjZSBvYmplY3RzLlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3QgZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBzb3VyY2VzIGZyb20gd2hpY2ggcHJvcGVydGllcyBhcmUgcHVsbGVkXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBkZXN0XG4gKi9cbmV4cG9ydHMuZXh0ZW5kID0gZnVuY3Rpb24gKGRlc3QpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3JjID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrIGluIHNyYykge1xuICAgICAgICAgICAgZGVzdFtrXSA9IHNyY1trXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn07XG5cbi8qKlxuICogRXh0ZW5kIGEgZGVzdGluYXRpb24gb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb2YgdGhlIHNyYyBvYmplY3QsXG4gKiB1c2luZyBkZWZpbmVQcm9wZXJ0eSBpbnN0ZWFkIG9mIHNpbXBsZSBhc3NpZ25tZW50LlxuICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBzcmNcbiAqIEByZXR1cm5zIHtPYmplY3R9IGRlc3RcbiAqL1xuZXhwb3J0cy5leHRlbmRBbGwgPSBmdW5jdGlvbiAoZGVzdCwgc3JjKSB7XG4gICAgZm9yICh2YXIgaSBpbiBzcmMpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIGksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc3JjLCBpKSk7XG4gICAgfVxuICAgIHJldHVybiBkZXN0O1xufTtcblxuLyoqXG4gKiBFeHRlbmQgYSBwYXJlbnQncyBwcm90b3R5cGUgd2l0aCBhbGwgcHJvcGVydGllcyBpbiBhIHByb3BlcnRpZXNcbiAqIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyZW50XG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAqIEByZXR1cm5zIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuaW5oZXJpdCA9IGZ1bmN0aW9uIChwYXJlbnQsIHByb3BzKSB7XG4gICAgdmFyIHBhcmVudFByb3RvID0gdHlwZW9mIHBhcmVudCA9PT0gJ2Z1bmN0aW9uJyA/IHBhcmVudC5wcm90b3R5cGUgOiBwYXJlbnQsXG4gICAgICAgIHByb3RvID0gT2JqZWN0LmNyZWF0ZShwYXJlbnRQcm90byk7XG4gICAgZXhwb3J0cy5leHRlbmRBbGwocHJvdG8sIHByb3BzKTtcbiAgICByZXR1cm4gcHJvdG87XG59O1xuXG4vKipcbiAqIEdpdmVuIGFuIG9iamVjdCBhbmQgYSBudW1iZXIgb2YgcHJvcGVydGllcyBhcyBzdHJpbmdzLCByZXR1cm4gdmVyc2lvblxuICogb2YgdGhhdCBvYmplY3Qgd2l0aCBvbmx5IHRob3NlIHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHNyYyB0aGUgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IHByb3BlcnRpZXMgYW4gYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgY2hvc2VuXG4gKiB0byBhcHBlYXIgb24gdGhlIHJlc3VsdGluZyBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3Qgd2l0aCBsaW1pdGVkIHByb3BlcnRpZXMuXG4gKiBAZXhhbXBsZVxuICogdmFyIGZvbyA9IHsgbmFtZTogJ0NoYXJsaWUnLCBhZ2U6IDEwIH07XG4gKiB2YXIganVzdE5hbWUgPSBwaWNrKGZvbywgWyduYW1lJ10pO1xuICogLy8ganVzdE5hbWUgPSB7IG5hbWU6ICdDaGFybGllJyB9XG4gKi9cbmV4cG9ydHMucGljayA9IGZ1bmN0aW9uIChzcmMsIHByb3BlcnRpZXMpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgaWYgKGsgaW4gc3JjKSB7XG4gICAgICAgICAgICByZXN1bHRba10gPSBzcmNba107XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbnZhciBpZCA9IDE7XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pcXVlIG51bWVyaWMgaWQsIHN0YXJ0aW5nIGF0IDEgYW5kIGluY3JlbWVudGluZyB3aXRoXG4gKiBlYWNoIGNhbGwuXG4gKlxuICogQHJldHVybnMge051bWJlcn0gdW5pcXVlIG51bWVyaWMgaWQuXG4gKi9cbmV4cG9ydHMudW5pcXVlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGlkKys7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIHZlcnNpb24gb2YgYGZuYCB0aGF0IG9ubHkgZmlyZXMgb25jZSBldmVyeSBgdGltZWAgbWlsbHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gdGhlIGZ1bmN0aW9uIHRvIGJlIHRocm90dGxlZFxuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWUgbWlsbHNlY29uZHMgcmVxdWlyZWQgYmV0d2VlbiBmdW5jdGlvbiBjYWxsc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSB2YWx1ZSBvZiBgdGhpc2Agd2l0aCB3aGljaCB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IGRlYm91bmNlZCBmdW5jdGlvblxuICovXG5leHBvcnRzLnRocm90dGxlID0gZnVuY3Rpb24gKGZuLCB0aW1lLCBjb250ZXh0KSB7XG4gICAgdmFyIGxvY2ssIGFyZ3MsIHdyYXBwZXJGbiwgbGF0ZXI7XG5cbiAgICBsYXRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcbiAgICAgICAgbG9jayA9IGZhbHNlO1xuICAgICAgICBpZiAoYXJncykge1xuICAgICAgICAgICAgd3JhcHBlckZuLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgYXJncyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdyYXBwZXJGbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGxvY2spIHtcbiAgICAgICAgICAgIC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxuICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY2FsbCBhbmQgbG9jayB1bnRpbCBsYXRlclxuICAgICAgICAgICAgZm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xuICAgICAgICAgICAgbG9jayA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHdyYXBwZXJGbjtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgdmVyc2lvbiBvZiBgZm5gIHRoYXQgaXMgb25seSBjYWxsZWQgYHRpbWVgIG1pbGxpc2Vjb25kc1xuICogYWZ0ZXIgaXRzIGxhc3QgaW52b2NhdGlvblxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIHRoZSBmdW5jdGlvbiB0byBiZSBkZWJvdW5jZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lIG1pbGxzZWNvbmRzIGFmdGVyIHdoaWNoIHRoZSBmdW5jdGlvbiB3aWxsIGJlIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZGVib3VuY2VkIGZ1bmN0aW9uXG4gKi9cbmV4cG9ydHMuZGVib3VuY2UgPSBmdW5jdGlvbihmbiwgdGltZSkge1xuICAgIHZhciB0aW1lciwgYXJncztcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcblxuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgfSwgdGltZSk7XG4gICAgfTtcbn07XG5cbi8qKlxuICogR2l2ZW4gYW4gYXJyYXkgb2YgbWVtYmVyIGZ1bmN0aW9uIG5hbWVzIGFzIHN0cmluZ3MsIHJlcGxhY2UgYWxsIG9mIHRoZW1cbiAqIHdpdGggYm91bmQgdmVyc2lvbnMgdGhhdCB3aWxsIGFsd2F5cyByZWZlciB0byBgY29udGV4dGAgYXMgYHRoaXNgLiBUaGlzXG4gKiBpcyB1c2VmdWwgZm9yIGNsYXNzZXMgd2hlcmUgb3RoZXJ3aXNlIGV2ZW50IGJpbmRpbmdzIHdvdWxkIHJlYXNzaWduXG4gKiBgdGhpc2AgdG8gdGhlIGV2ZW50ZWQgb2JqZWN0IG9yIHNvbWUgb3RoZXIgdmFsdWU6IHRoaXMgbGV0cyB5b3UgZW5zdXJlXG4gKiB0aGUgYHRoaXNgIHZhbHVlIGFsd2F5cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGZucyBsaXN0IG9mIG1lbWJlciBmdW5jdGlvbiBuYW1lc1xuICogQHBhcmFtIHsqfSBjb250ZXh0IHRoZSBjb250ZXh0IHZhbHVlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfSBjaGFuZ2VzIGZ1bmN0aW9ucyBpbi1wbGFjZVxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIE15Q2xhc3MoKSB7XG4gKiAgIGJpbmRBbGwoWydvbnRpbWVyJ10sIHRoaXMpO1xuICogICB0aGlzLm5hbWUgPSAnVG9tJztcbiAqIH1cbiAqIE15Q2xhc3MucHJvdG90eXBlLm9udGltZXIgPSBmdW5jdGlvbigpIHtcbiAqICAgYWxlcnQodGhpcy5uYW1lKTtcbiAqIH07XG4gKiB2YXIgbXlDbGFzcyA9IG5ldyBNeUNsYXNzKCk7XG4gKiBzZXRUaW1lb3V0KG15Q2xhc3Mub250aW1lciwgMTAwKTtcbiAqL1xuZXhwb3J0cy5iaW5kQWxsID0gZnVuY3Rpb24oZm5zLCBjb250ZXh0KSB7XG4gICAgZm5zLmZvckVhY2goZnVuY3Rpb24oZm4pIHtcbiAgICAgICAgY29udGV4dFtmbl0gPSBjb250ZXh0W2ZuXS5iaW5kKGNvbnRleHQpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlICdvcHRpb25zJyBwcm9wZXJ0eSBvbiBgb2JqYCB3aXRoIHByb3BlcnRpZXNcbiAqIGZyb20gdGhlIGBvcHRpb25zYCBhcmd1bWVudC4gUHJvcGVydGllcyBpbiB0aGUgYG9wdGlvbnNgXG4gKiBvYmplY3Qgd2lsbCBvdmVycmlkZSBleGlzdGluZyBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogZGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvYmplY3Qgb2Ygb3ZlcnJpZGUgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gZGVyaXZlZCBvcHRpb25zIG9iamVjdC5cbiAqL1xuZXhwb3J0cy5zZXRPcHRpb25zID0gZnVuY3Rpb24ob2JqLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSkge1xuICAgICAgICBvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gT2JqZWN0LmNyZWF0ZShvYmoub3B0aW9ucykgOiB7fTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XG4gICAgICAgIG9iai5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG9iai5vcHRpb25zO1xufTtcbiIsIi8vIChjKSBEZWFuIE1jTmFtZWUgPGRlYW5AZ21haWwuY29tPiwgMjAxMi5cbi8vXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZGVhbm0vY3NzLWNvbG9yLXBhcnNlci1qc1xuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4vLyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4vLyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtY29sb3IvXG52YXIga0NTU0NvbG9yVGFibGUgPSB7XG4gIFwidHJhbnNwYXJlbnRcIjogWzAsMCwwLDBdLCBcImFsaWNlYmx1ZVwiOiBbMjQwLDI0OCwyNTUsMV0sXG4gIFwiYW50aXF1ZXdoaXRlXCI6IFsyNTAsMjM1LDIxNSwxXSwgXCJhcXVhXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiYXF1YW1hcmluZVwiOiBbMTI3LDI1NSwyMTIsMV0sIFwiYXp1cmVcIjogWzI0MCwyNTUsMjU1LDFdLFxuICBcImJlaWdlXCI6IFsyNDUsMjQ1LDIyMCwxXSwgXCJiaXNxdWVcIjogWzI1NSwyMjgsMTk2LDFdLFxuICBcImJsYWNrXCI6IFswLDAsMCwxXSwgXCJibGFuY2hlZGFsbW9uZFwiOiBbMjU1LDIzNSwyMDUsMV0sXG4gIFwiYmx1ZVwiOiBbMCwwLDI1NSwxXSwgXCJibHVldmlvbGV0XCI6IFsxMzgsNDMsMjI2LDFdLFxuICBcImJyb3duXCI6IFsxNjUsNDIsNDIsMV0sIFwiYnVybHl3b29kXCI6IFsyMjIsMTg0LDEzNSwxXSxcbiAgXCJjYWRldGJsdWVcIjogWzk1LDE1OCwxNjAsMV0sIFwiY2hhcnRyZXVzZVwiOiBbMTI3LDI1NSwwLDFdLFxuICBcImNob2NvbGF0ZVwiOiBbMjEwLDEwNSwzMCwxXSwgXCJjb3JhbFwiOiBbMjU1LDEyNyw4MCwxXSxcbiAgXCJjb3JuZmxvd2VyYmx1ZVwiOiBbMTAwLDE0OSwyMzcsMV0sIFwiY29ybnNpbGtcIjogWzI1NSwyNDgsMjIwLDFdLFxuICBcImNyaW1zb25cIjogWzIyMCwyMCw2MCwxXSwgXCJjeWFuXCI6IFswLDI1NSwyNTUsMV0sXG4gIFwiZGFya2JsdWVcIjogWzAsMCwxMzksMV0sIFwiZGFya2N5YW5cIjogWzAsMTM5LDEzOSwxXSxcbiAgXCJkYXJrZ29sZGVucm9kXCI6IFsxODQsMTM0LDExLDFdLCBcImRhcmtncmF5XCI6IFsxNjksMTY5LDE2OSwxXSxcbiAgXCJkYXJrZ3JlZW5cIjogWzAsMTAwLDAsMV0sIFwiZGFya2dyZXlcIjogWzE2OSwxNjksMTY5LDFdLFxuICBcImRhcmtraGFraVwiOiBbMTg5LDE4MywxMDcsMV0sIFwiZGFya21hZ2VudGFcIjogWzEzOSwwLDEzOSwxXSxcbiAgXCJkYXJrb2xpdmVncmVlblwiOiBbODUsMTA3LDQ3LDFdLCBcImRhcmtvcmFuZ2VcIjogWzI1NSwxNDAsMCwxXSxcbiAgXCJkYXJrb3JjaGlkXCI6IFsxNTMsNTAsMjA0LDFdLCBcImRhcmtyZWRcIjogWzEzOSwwLDAsMV0sXG4gIFwiZGFya3NhbG1vblwiOiBbMjMzLDE1MCwxMjIsMV0sIFwiZGFya3NlYWdyZWVuXCI6IFsxNDMsMTg4LDE0MywxXSxcbiAgXCJkYXJrc2xhdGVibHVlXCI6IFs3Miw2MSwxMzksMV0sIFwiZGFya3NsYXRlZ3JheVwiOiBbNDcsNzksNzksMV0sXG4gIFwiZGFya3NsYXRlZ3JleVwiOiBbNDcsNzksNzksMV0sIFwiZGFya3R1cnF1b2lzZVwiOiBbMCwyMDYsMjA5LDFdLFxuICBcImRhcmt2aW9sZXRcIjogWzE0OCwwLDIxMSwxXSwgXCJkZWVwcGlua1wiOiBbMjU1LDIwLDE0NywxXSxcbiAgXCJkZWVwc2t5Ymx1ZVwiOiBbMCwxOTEsMjU1LDFdLCBcImRpbWdyYXlcIjogWzEwNSwxMDUsMTA1LDFdLFxuICBcImRpbWdyZXlcIjogWzEwNSwxMDUsMTA1LDFdLCBcImRvZGdlcmJsdWVcIjogWzMwLDE0NCwyNTUsMV0sXG4gIFwiZmlyZWJyaWNrXCI6IFsxNzgsMzQsMzQsMV0sIFwiZmxvcmFsd2hpdGVcIjogWzI1NSwyNTAsMjQwLDFdLFxuICBcImZvcmVzdGdyZWVuXCI6IFszNCwxMzksMzQsMV0sIFwiZnVjaHNpYVwiOiBbMjU1LDAsMjU1LDFdLFxuICBcImdhaW5zYm9yb1wiOiBbMjIwLDIyMCwyMjAsMV0sIFwiZ2hvc3R3aGl0ZVwiOiBbMjQ4LDI0OCwyNTUsMV0sXG4gIFwiZ29sZFwiOiBbMjU1LDIxNSwwLDFdLCBcImdvbGRlbnJvZFwiOiBbMjE4LDE2NSwzMiwxXSxcbiAgXCJncmF5XCI6IFsxMjgsMTI4LDEyOCwxXSwgXCJncmVlblwiOiBbMCwxMjgsMCwxXSxcbiAgXCJncmVlbnllbGxvd1wiOiBbMTczLDI1NSw0NywxXSwgXCJncmV5XCI6IFsxMjgsMTI4LDEyOCwxXSxcbiAgXCJob25leWRld1wiOiBbMjQwLDI1NSwyNDAsMV0sIFwiaG90cGlua1wiOiBbMjU1LDEwNSwxODAsMV0sXG4gIFwiaW5kaWFucmVkXCI6IFsyMDUsOTIsOTIsMV0sIFwiaW5kaWdvXCI6IFs3NSwwLDEzMCwxXSxcbiAgXCJpdm9yeVwiOiBbMjU1LDI1NSwyNDAsMV0sIFwia2hha2lcIjogWzI0MCwyMzAsMTQwLDFdLFxuICBcImxhdmVuZGVyXCI6IFsyMzAsMjMwLDI1MCwxXSwgXCJsYXZlbmRlcmJsdXNoXCI6IFsyNTUsMjQwLDI0NSwxXSxcbiAgXCJsYXduZ3JlZW5cIjogWzEyNCwyNTIsMCwxXSwgXCJsZW1vbmNoaWZmb25cIjogWzI1NSwyNTAsMjA1LDFdLFxuICBcImxpZ2h0Ymx1ZVwiOiBbMTczLDIxNiwyMzAsMV0sIFwibGlnaHRjb3JhbFwiOiBbMjQwLDEyOCwxMjgsMV0sXG4gIFwibGlnaHRjeWFuXCI6IFsyMjQsMjU1LDI1NSwxXSwgXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiOiBbMjUwLDI1MCwyMTAsMV0sXG4gIFwibGlnaHRncmF5XCI6IFsyMTEsMjExLDIxMSwxXSwgXCJsaWdodGdyZWVuXCI6IFsxNDQsMjM4LDE0NCwxXSxcbiAgXCJsaWdodGdyZXlcIjogWzIxMSwyMTEsMjExLDFdLCBcImxpZ2h0cGlua1wiOiBbMjU1LDE4MiwxOTMsMV0sXG4gIFwibGlnaHRzYWxtb25cIjogWzI1NSwxNjAsMTIyLDFdLCBcImxpZ2h0c2VhZ3JlZW5cIjogWzMyLDE3OCwxNzAsMV0sXG4gIFwibGlnaHRza3libHVlXCI6IFsxMzUsMjA2LDI1MCwxXSwgXCJsaWdodHNsYXRlZ3JheVwiOiBbMTE5LDEzNiwxNTMsMV0sXG4gIFwibGlnaHRzbGF0ZWdyZXlcIjogWzExOSwxMzYsMTUzLDFdLCBcImxpZ2h0c3RlZWxibHVlXCI6IFsxNzYsMTk2LDIyMiwxXSxcbiAgXCJsaWdodHllbGxvd1wiOiBbMjU1LDI1NSwyMjQsMV0sIFwibGltZVwiOiBbMCwyNTUsMCwxXSxcbiAgXCJsaW1lZ3JlZW5cIjogWzUwLDIwNSw1MCwxXSwgXCJsaW5lblwiOiBbMjUwLDI0MCwyMzAsMV0sXG4gIFwibWFnZW50YVwiOiBbMjU1LDAsMjU1LDFdLCBcIm1hcm9vblwiOiBbMTI4LDAsMCwxXSxcbiAgXCJtZWRpdW1hcXVhbWFyaW5lXCI6IFsxMDIsMjA1LDE3MCwxXSwgXCJtZWRpdW1ibHVlXCI6IFswLDAsMjA1LDFdLFxuICBcIm1lZGl1bW9yY2hpZFwiOiBbMTg2LDg1LDIxMSwxXSwgXCJtZWRpdW1wdXJwbGVcIjogWzE0NywxMTIsMjE5LDFdLFxuICBcIm1lZGl1bXNlYWdyZWVuXCI6IFs2MCwxNzksMTEzLDFdLCBcIm1lZGl1bXNsYXRlYmx1ZVwiOiBbMTIzLDEwNCwyMzgsMV0sXG4gIFwibWVkaXVtc3ByaW5nZ3JlZW5cIjogWzAsMjUwLDE1NCwxXSwgXCJtZWRpdW10dXJxdW9pc2VcIjogWzcyLDIwOSwyMDQsMV0sXG4gIFwibWVkaXVtdmlvbGV0cmVkXCI6IFsxOTksMjEsMTMzLDFdLCBcIm1pZG5pZ2h0Ymx1ZVwiOiBbMjUsMjUsMTEyLDFdLFxuICBcIm1pbnRjcmVhbVwiOiBbMjQ1LDI1NSwyNTAsMV0sIFwibWlzdHlyb3NlXCI6IFsyNTUsMjI4LDIyNSwxXSxcbiAgXCJtb2NjYXNpblwiOiBbMjU1LDIyOCwxODEsMV0sIFwibmF2YWpvd2hpdGVcIjogWzI1NSwyMjIsMTczLDFdLFxuICBcIm5hdnlcIjogWzAsMCwxMjgsMV0sIFwib2xkbGFjZVwiOiBbMjUzLDI0NSwyMzAsMV0sXG4gIFwib2xpdmVcIjogWzEyOCwxMjgsMCwxXSwgXCJvbGl2ZWRyYWJcIjogWzEwNywxNDIsMzUsMV0sXG4gIFwib3JhbmdlXCI6IFsyNTUsMTY1LDAsMV0sIFwib3JhbmdlcmVkXCI6IFsyNTUsNjksMCwxXSxcbiAgXCJvcmNoaWRcIjogWzIxOCwxMTIsMjE0LDFdLCBcInBhbGVnb2xkZW5yb2RcIjogWzIzOCwyMzIsMTcwLDFdLFxuICBcInBhbGVncmVlblwiOiBbMTUyLDI1MSwxNTIsMV0sIFwicGFsZXR1cnF1b2lzZVwiOiBbMTc1LDIzOCwyMzgsMV0sXG4gIFwicGFsZXZpb2xldHJlZFwiOiBbMjE5LDExMiwxNDcsMV0sIFwicGFwYXlhd2hpcFwiOiBbMjU1LDIzOSwyMTMsMV0sXG4gIFwicGVhY2hwdWZmXCI6IFsyNTUsMjE4LDE4NSwxXSwgXCJwZXJ1XCI6IFsyMDUsMTMzLDYzLDFdLFxuICBcInBpbmtcIjogWzI1NSwxOTIsMjAzLDFdLCBcInBsdW1cIjogWzIyMSwxNjAsMjIxLDFdLFxuICBcInBvd2RlcmJsdWVcIjogWzE3NiwyMjQsMjMwLDFdLCBcInB1cnBsZVwiOiBbMTI4LDAsMTI4LDFdLFxuICBcInJlZFwiOiBbMjU1LDAsMCwxXSwgXCJyb3N5YnJvd25cIjogWzE4OCwxNDMsMTQzLDFdLFxuICBcInJveWFsYmx1ZVwiOiBbNjUsMTA1LDIyNSwxXSwgXCJzYWRkbGVicm93blwiOiBbMTM5LDY5LDE5LDFdLFxuICBcInNhbG1vblwiOiBbMjUwLDEyOCwxMTQsMV0sIFwic2FuZHlicm93blwiOiBbMjQ0LDE2NCw5NiwxXSxcbiAgXCJzZWFncmVlblwiOiBbNDYsMTM5LDg3LDFdLCBcInNlYXNoZWxsXCI6IFsyNTUsMjQ1LDIzOCwxXSxcbiAgXCJzaWVubmFcIjogWzE2MCw4Miw0NSwxXSwgXCJzaWx2ZXJcIjogWzE5MiwxOTIsMTkyLDFdLFxuICBcInNreWJsdWVcIjogWzEzNSwyMDYsMjM1LDFdLCBcInNsYXRlYmx1ZVwiOiBbMTA2LDkwLDIwNSwxXSxcbiAgXCJzbGF0ZWdyYXlcIjogWzExMiwxMjgsMTQ0LDFdLCBcInNsYXRlZ3JleVwiOiBbMTEyLDEyOCwxNDQsMV0sXG4gIFwic25vd1wiOiBbMjU1LDI1MCwyNTAsMV0sIFwic3ByaW5nZ3JlZW5cIjogWzAsMjU1LDEyNywxXSxcbiAgXCJzdGVlbGJsdWVcIjogWzcwLDEzMCwxODAsMV0sIFwidGFuXCI6IFsyMTAsMTgwLDE0MCwxXSxcbiAgXCJ0ZWFsXCI6IFswLDEyOCwxMjgsMV0sIFwidGhpc3RsZVwiOiBbMjE2LDE5MSwyMTYsMV0sXG4gIFwidG9tYXRvXCI6IFsyNTUsOTksNzEsMV0sIFwidHVycXVvaXNlXCI6IFs2NCwyMjQsMjA4LDFdLFxuICBcInZpb2xldFwiOiBbMjM4LDEzMCwyMzgsMV0sIFwid2hlYXRcIjogWzI0NSwyMjIsMTc5LDFdLFxuICBcIndoaXRlXCI6IFsyNTUsMjU1LDI1NSwxXSwgXCJ3aGl0ZXNtb2tlXCI6IFsyNDUsMjQ1LDI0NSwxXSxcbiAgXCJ5ZWxsb3dcIjogWzI1NSwyNTUsMCwxXSwgXCJ5ZWxsb3dncmVlblwiOiBbMTU0LDIwNSw1MCwxXX1cblxuZnVuY3Rpb24gY2xhbXBfY3NzX2J5dGUoaSkgeyAgLy8gQ2xhbXAgdG8gaW50ZWdlciAwIC4uIDI1NS5cbiAgaSA9IE1hdGgucm91bmQoaSk7ICAvLyBTZWVtcyB0byBiZSB3aGF0IENocm9tZSBkb2VzICh2cyB0cnVuY2F0aW9uKS5cbiAgcmV0dXJuIGkgPCAwID8gMCA6IGkgPiAyNTUgPyAyNTUgOiBpO1xufVxuXG5mdW5jdGlvbiBjbGFtcF9jc3NfZmxvYXQoZikgeyAgLy8gQ2xhbXAgdG8gZmxvYXQgMC4wIC4uIDEuMC5cbiAgcmV0dXJuIGYgPCAwID8gMCA6IGYgPiAxID8gMSA6IGY7XG59XG5cbmZ1bmN0aW9uIHBhcnNlX2Nzc19pbnQoc3RyKSB7ICAvLyBpbnQgb3IgcGVyY2VudGFnZS5cbiAgaWYgKHN0cltzdHIubGVuZ3RoIC0gMV0gPT09ICclJylcbiAgICByZXR1cm4gY2xhbXBfY3NzX2J5dGUocGFyc2VGbG9hdChzdHIpIC8gMTAwICogMjU1KTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19ieXRlKHBhcnNlSW50KHN0cikpO1xufVxuXG5mdW5jdGlvbiBwYXJzZV9jc3NfZmxvYXQoc3RyKSB7ICAvLyBmbG9hdCBvciBwZXJjZW50YWdlLlxuICBpZiAoc3RyW3N0ci5sZW5ndGggLSAxXSA9PT0gJyUnKVxuICAgIHJldHVybiBjbGFtcF9jc3NfZmxvYXQocGFyc2VGbG9hdChzdHIpIC8gMTAwKTtcbiAgcmV0dXJuIGNsYW1wX2Nzc19mbG9hdChwYXJzZUZsb2F0KHN0cikpO1xufVxuXG5mdW5jdGlvbiBjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgpIHtcbiAgaWYgKGggPCAwKSBoICs9IDE7XG4gIGVsc2UgaWYgKGggPiAxKSBoIC09IDE7XG5cbiAgaWYgKGggKiA2IDwgMSkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogaCAqIDY7XG4gIGlmIChoICogMiA8IDEpIHJldHVybiBtMjtcbiAgaWYgKGggKiAzIDwgMikgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDIvMyAtIGgpICogNjtcbiAgcmV0dXJuIG0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNTU0NvbG9yKGNzc19zdHIpIHtcbiAgLy8gUmVtb3ZlIGFsbCB3aGl0ZXNwYWNlLCBub3QgY29tcGxpYW50LCBidXQgc2hvdWxkIGp1c3QgYmUgbW9yZSBhY2NlcHRpbmcuXG4gIHZhciBzdHIgPSBjc3Nfc3RyLnJlcGxhY2UoLyAvZywgJycpLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gQ29sb3Iga2V5d29yZHMgKGFuZCB0cmFuc3BhcmVudCkgbG9va3VwLlxuICBpZiAoc3RyIGluIGtDU1NDb2xvclRhYmxlKSByZXR1cm4ga0NTU0NvbG9yVGFibGVbc3RyXS5zbGljZSgpOyAgLy8gZHVwLlxuXG4gIC8vICNhYmMgYW5kICNhYmMxMjMgc3ludGF4LlxuICBpZiAoc3RyWzBdID09PSAnIycpIHtcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gNCkge1xuICAgICAgdmFyIGl2ID0gcGFyc2VJbnQoc3RyLnN1YnN0cigxKSwgMTYpOyAgLy8gVE9ETyhkZWFubSk6IFN0cmljdGVyIHBhcnNpbmcuXG4gICAgICBpZiAoIShpdiA+PSAwICYmIGl2IDw9IDB4ZmZmKSkgcmV0dXJuIG51bGw7ICAvLyBDb3ZlcnMgTmFOLlxuICAgICAgcmV0dXJuIFsoKGl2ICYgMHhmMDApID4+IDQpIHwgKChpdiAmIDB4ZjAwKSA+PiA4KSxcbiAgICAgICAgICAgICAgKGl2ICYgMHhmMCkgfCAoKGl2ICYgMHhmMCkgPj4gNCksXG4gICAgICAgICAgICAgIChpdiAmIDB4ZikgfCAoKGl2ICYgMHhmKSA8PCA0KSxcbiAgICAgICAgICAgICAgMV07XG4gICAgfSBlbHNlIGlmIChzdHIubGVuZ3RoID09PSA3KSB7XG4gICAgICB2YXIgaXYgPSBwYXJzZUludChzdHIuc3Vic3RyKDEpLCAxNik7ICAvLyBUT0RPKGRlYW5tKTogU3RyaWN0ZXIgcGFyc2luZy5cbiAgICAgIGlmICghKGl2ID49IDAgJiYgaXYgPD0gMHhmZmZmZmYpKSByZXR1cm4gbnVsbDsgIC8vIENvdmVycyBOYU4uXG4gICAgICByZXR1cm4gWyhpdiAmIDB4ZmYwMDAwKSA+PiAxNixcbiAgICAgICAgICAgICAgKGl2ICYgMHhmZjAwKSA+PiA4LFxuICAgICAgICAgICAgICBpdiAmIDB4ZmYsXG4gICAgICAgICAgICAgIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIG9wID0gc3RyLmluZGV4T2YoJygnKSwgZXAgPSBzdHIuaW5kZXhPZignKScpO1xuICBpZiAob3AgIT09IC0xICYmIGVwICsgMSA9PT0gc3RyLmxlbmd0aCkge1xuICAgIHZhciBmbmFtZSA9IHN0ci5zdWJzdHIoMCwgb3ApO1xuICAgIHZhciBwYXJhbXMgPSBzdHIuc3Vic3RyKG9wKzEsIGVwLShvcCsxKSkuc3BsaXQoJywnKTtcbiAgICB2YXIgYWxwaGEgPSAxOyAgLy8gVG8gYWxsb3cgY2FzZSBmYWxsdGhyb3VnaC5cbiAgICBzd2l0Y2ggKGZuYW1lKSB7XG4gICAgICBjYXNlICdyZ2JhJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDQpIHJldHVybiBudWxsO1xuICAgICAgICBhbHBoYSA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXMucG9wKCkpO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2guXG4gICAgICBjYXNlICdyZ2InOlxuICAgICAgICBpZiAocGFyYW1zLmxlbmd0aCAhPT0gMykgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBbcGFyc2VfY3NzX2ludChwYXJhbXNbMF0pLFxuICAgICAgICAgICAgICAgIHBhcnNlX2Nzc19pbnQocGFyYW1zWzFdKSxcbiAgICAgICAgICAgICAgICBwYXJzZV9jc3NfaW50KHBhcmFtc1syXSksXG4gICAgICAgICAgICAgICAgYWxwaGFdO1xuICAgICAgY2FzZSAnaHNsYSc6XG4gICAgICAgIGlmIChwYXJhbXMubGVuZ3RoICE9PSA0KSByZXR1cm4gbnVsbDtcbiAgICAgICAgYWxwaGEgPSBwYXJzZV9jc3NfZmxvYXQocGFyYW1zLnBvcCgpKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoLlxuICAgICAgY2FzZSAnaHNsJzpcbiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgaCA9ICgoKHBhcnNlRmxvYXQocGFyYW1zWzBdKSAlIDM2MCkgKyAzNjApICUgMzYwKSAvIDM2MDsgIC8vIDAgLi4gMVxuICAgICAgICAvLyBOT1RFKGRlYW5tKTogQWNjb3JkaW5nIHRvIHRoZSBDU1Mgc3BlYyBzL2wgc2hvdWxkIG9ubHkgYmVcbiAgICAgICAgLy8gcGVyY2VudGFnZXMsIGJ1dCB3ZSBkb24ndCBib3RoZXIgYW5kIGxldCBmbG9hdCBvciBwZXJjZW50YWdlLlxuICAgICAgICB2YXIgcyA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMV0pO1xuICAgICAgICB2YXIgbCA9IHBhcnNlX2Nzc19mbG9hdChwYXJhbXNbMl0pO1xuICAgICAgICB2YXIgbTIgPSBsIDw9IDAuNSA/IGwgKiAocyArIDEpIDogbCArIHMgLSBsICogcztcbiAgICAgICAgdmFyIG0xID0gbCAqIDIgLSBtMjtcbiAgICAgICAgcmV0dXJuIFtjbGFtcF9jc3NfYnl0ZShjc3NfaHVlX3RvX3JnYihtMSwgbTIsIGgrMS8zKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoKSAqIDI1NSksXG4gICAgICAgICAgICAgICAgY2xhbXBfY3NzX2J5dGUoY3NzX2h1ZV90b19yZ2IobTEsIG0yLCBoLTEvMykgKiAyNTUpLFxuICAgICAgICAgICAgICAgIGFscGhhXTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG50cnkgeyBleHBvcnRzLnBhcnNlQ1NTQ29sb3IgPSBwYXJzZUNTU0NvbG9yIH0gY2F0Y2goZSkgeyB9XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZVR5cGVzID0gWydVbmtub3duJywgJ1BvaW50JywgJ0xpbmVTdHJpbmcnLCAnUG9seWdvbiddO1xuXG5mdW5jdGlvbiBpbmZpeChvcGVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiAndCcgKyBvcGVyYXRvciArIFZlY3RvclRpbGVGZWF0dXJlVHlwZXMuaW5kZXhPZih2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXScgKyBvcGVyYXRvciArIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdEluZml4KG9wZXJhdG9yKSB7XG4gICAgdmFyIG5vbnN0cmljdEluZml4ID0gaW5maXgob3BlcmF0b3IpO1xuICAgIHJldHVybiBmdW5jdGlvbihfLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICckdHlwZScpIHtcbiAgICAgICAgICAgIHJldHVybiBub25zdHJpY3RJbmZpeChfLCBrZXksIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAndHlwZW9mKHBbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSkgPT09IHR5cGVvZignICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpICsgJykgJiYgJyArXG4gICAgICAgICAgICAgICAgbm9uc3RyaWN0SW5maXgoXywga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgb3BlcmF0b3JzID0ge1xuICAgICc9PSc6IGluZml4KCc9PT0nKSxcbiAgICAnIT0nOiBpbmZpeCgnIT09JyksXG4gICAgJz4nOiBzdHJpY3RJbmZpeCgnPicpLFxuICAgICc8Jzogc3RyaWN0SW5maXgoJzwnKSxcbiAgICAnPD0nOiBzdHJpY3RJbmZpeCgnPD0nKSxcbiAgICAnPj0nOiBzdHJpY3RJbmZpeCgnPj0nKSxcbiAgICAnaW4nOiBmdW5jdGlvbihfLCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMikubWFwKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gJygnICsgb3BlcmF0b3JzWyc9PSddKF8sIGtleSwgdmFsdWUpICsgJyknO1xuICAgICAgICB9KS5qb2luKCd8fCcpIHx8ICdmYWxzZSc7XG4gICAgfSxcbiAgICAnIWluJzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAnISgnICsgb3BlcmF0b3JzLmluLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKyAnKSc7XG4gICAgfSxcbiAgICAnYW55JzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLm1hcChmdW5jdGlvbihmaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBjb21waWxlKGZpbHRlcikgKyAnKSc7XG4gICAgICAgIH0pLmpvaW4oJ3x8JykgfHwgJ2ZhbHNlJztcbiAgICB9LFxuICAgICdhbGwnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkubWFwKGZ1bmN0aW9uKGZpbHRlcikge1xuICAgICAgICAgICAgcmV0dXJuICcoJyArIGNvbXBpbGUoZmlsdGVyKSArICcpJztcbiAgICAgICAgfSkuam9pbignJiYnKSB8fCAndHJ1ZSc7XG4gICAgfSxcbiAgICAnbm9uZSc6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gJyEoJyArIG9wZXJhdG9ycy5hbnkuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICcpJztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb21waWxlKGZpbHRlcikge1xuICAgIHJldHVybiBvcGVyYXRvcnNbZmlsdGVyWzBdXS5hcHBseShmaWx0ZXIsIGZpbHRlcik7XG59XG5cbmZ1bmN0aW9uIHRydXRoKCkge1xuICAgIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgZmlsdGVyIGV4cHJlc3NlZCBhcyBuZXN0ZWQgYXJyYXlzLCByZXR1cm4gYSBuZXcgZnVuY3Rpb25cbiAqIHRoYXQgZXZhbHVhdGVzIHdoZXRoZXIgYSBnaXZlbiBmZWF0dXJlICh3aXRoIGEgLnByb3BlcnRpZXMgb3IgLnRhZ3MgcHJvcGVydHkpXG4gKiBwYXNzZXMgaXRzIHRlc3QuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gZmlsdGVyIG1hcGJveCBnbCBmaWx0ZXJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gZmlsdGVyLWV2YWx1YXRpbmcgZnVuY3Rpb25cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgaWYgKCFmaWx0ZXIpIHJldHVybiB0cnV0aDtcbiAgICB2YXIgZmlsdGVyU3RyID0gJ3ZhciBwID0gZi5wcm9wZXJ0aWVzIHx8IGYudGFncyB8fCB7fSwgdCA9IGYudHlwZTsgcmV0dXJuICcgKyBjb21waWxlKGZpbHRlcikgKyAnOyc7XG4gICAgLy8ganNoaW50IGV2aWw6IHRydWVcbiAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCdmJywgZmlsdGVyU3RyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY2xpcDtcblxuLyogY2xpcCBmZWF0dXJlcyBiZXR3ZWVuIHR3byBheGlzLXBhcmFsbGVsIGxpbmVzOlxuICogICAgIHwgICAgICAgIHxcbiAqICBfX198X19fICAgICB8ICAgICAvXG4gKiAvICAgfCAgIFxcX19fX3xfX19fL1xuICogICAgIHwgICAgICAgIHxcbiAqL1xuXG5mdW5jdGlvbiBjbGlwKGZlYXR1cmVzLCBzY2FsZSwgazEsIGsyLCBheGlzLCBpbnRlcnNlY3QpIHtcblxuICAgIGsxIC89IHNjYWxlO1xuICAgIGsyIC89IHNjYWxlO1xuXG4gICAgdmFyIGNsaXBwZWQgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldLFxuICAgICAgICAgICAgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICAgICAgdHlwZSA9IGZlYXR1cmUudHlwZSxcbiAgICAgICAgICAgIG1pbiwgbWF4O1xuXG4gICAgICAgIGlmIChmZWF0dXJlLm1pbikge1xuICAgICAgICAgICAgbWluID0gZmVhdHVyZS5taW5bYXhpc107XG4gICAgICAgICAgICBtYXggPSBmZWF0dXJlLm1heFtheGlzXTtcblxuICAgICAgICAgICAgaWYgKG1pbiA+PSBrMSAmJiBtYXggPD0gazIpIHsgLy8gdHJpdmlhbCBhY2NlcHRcbiAgICAgICAgICAgICAgICBjbGlwcGVkLnB1c2goZmVhdHVyZSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1pbiA+IGsyIHx8IG1heCA8IGsxKSBjb250aW51ZTsgLy8gdHJpdmlhbCByZWplY3RcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzbGljZXMgPSB0eXBlID09PSAxID9cbiAgICAgICAgICAgICAgICBjbGlwUG9pbnRzKGdlb21ldHJ5LCBrMSwgazIsIGF4aXMpIDpcbiAgICAgICAgICAgICAgICBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCB0eXBlID09PSAzKTtcblxuICAgICAgICBpZiAoc2xpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gaWYgYSBmZWF0dXJlIGdvdCBjbGlwcGVkLCBpdCB3aWxsIGxpa2VseSBnZXQgY2xpcHBlZCBvbiB0aGUgbmV4dCB6b29tIGxldmVsIGFzIHdlbGwsXG4gICAgICAgICAgICAvLyBzbyB0aGVyZSdzIG5vIG5lZWQgdG8gcmVjYWxjdWxhdGUgYmJveGVzXG4gICAgICAgICAgICBjbGlwcGVkLnB1c2goe1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5OiBzbGljZXMsXG4gICAgICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgICAgICB0YWdzOiBmZWF0dXJlc1tpXS50YWdzIHx8IG51bGxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaXBwZWQubGVuZ3RoID8gY2xpcHBlZCA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGNsaXBQb2ludHMoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcykge1xuICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBnZW9tZXRyeS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYSA9IGdlb21ldHJ5W2ldLFxuICAgICAgICAgICAgYWsgPSBhW2F4aXNdO1xuXG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcbiAgICB9XG4gICAgcmV0dXJuIHNsaWNlO1xufVxuXG5mdW5jdGlvbiBjbGlwR2VvbWV0cnkoZ2VvbWV0cnksIGsxLCBrMiwgYXhpcywgaW50ZXJzZWN0LCBjbG9zZWQpIHtcblxuICAgIHZhciBzbGljZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB2YXIgYWsgPSAwLFxuICAgICAgICAgICAgYmsgPSAwLFxuICAgICAgICAgICAgYiA9IG51bGwsXG4gICAgICAgICAgICBwb2ludHMgPSBnZW9tZXRyeVtpXSxcbiAgICAgICAgICAgIGFyZWEgPSBwb2ludHMuYXJlYSxcbiAgICAgICAgICAgIGRpc3QgPSBwb2ludHMuZGlzdCxcbiAgICAgICAgICAgIGxlbiA9IHBvaW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhLCBqO1xuXG4gICAgICAgIHZhciBzbGljZSA9IFtdO1xuXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW4gLSAxOyBqKyspIHtcbiAgICAgICAgICAgIGEgPSBiIHx8IHBvaW50c1tqXTtcbiAgICAgICAgICAgIGIgPSBwb2ludHNbaiArIDFdO1xuICAgICAgICAgICAgYWsgPSBiayB8fCBhW2F4aXNdO1xuICAgICAgICAgICAgYmsgPSBiW2F4aXNdO1xuXG4gICAgICAgICAgICBpZiAoYWsgPCBrMSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKChiayA+IGsyKSkgeyAvLyAtLS18LS0tLS18LS0+XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSwgaW50ZXJzZWN0KGEsIGIsIGsyKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+PSBrMSkgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazEpKTsgLy8gLS0tfC0tPiAgfFxuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFrID4gazIpIHtcblxuICAgICAgICAgICAgICAgIGlmICgoYmsgPCBrMSkpIHsgLy8gPC0tfC0tLS0tfC0tLVxuICAgICAgICAgICAgICAgICAgICBzbGljZS5wdXNoKGludGVyc2VjdChhLCBiLCBrMiksIGludGVyc2VjdChhLCBiLCBrMSkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb3NlZCkgc2xpY2UgPSBuZXdTbGljZShzbGljZXMsIHNsaWNlLCBhcmVhLCBkaXN0KTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmsgPD0gazIpIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsyKSk7IC8vIHwgIDwtLXwtLS1cblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goYSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYmsgPCBrMSkgeyAvLyA8LS18LS0tICB8XG4gICAgICAgICAgICAgICAgICAgIHNsaWNlLnB1c2goaW50ZXJzZWN0KGEsIGIsIGsxKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2xvc2VkKSBzbGljZSA9IG5ld1NsaWNlKHNsaWNlcywgc2xpY2UsIGFyZWEsIGRpc3QpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiayA+IGsyKSB7IC8vIHwgIC0tLXwtLT5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2UucHVzaChpbnRlcnNlY3QoYSwgYiwgazIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjbG9zZWQpIHNsaWNlID0gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHwgLS0+IHxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkZCB0aGUgbGFzdCBwb2ludFxuICAgICAgICBhID0gcG9pbnRzW2xlbiAtIDFdO1xuICAgICAgICBhayA9IGFbYXhpc107XG4gICAgICAgIGlmIChhayA+PSBrMSAmJiBhayA8PSBrMikgc2xpY2UucHVzaChhKTtcblxuICAgICAgICAvLyBjbG9zZSB0aGUgcG9seWdvbiBpZiBpdHMgZW5kcG9pbnRzIGFyZSBub3QgdGhlIHNhbWUgYWZ0ZXIgY2xpcHBpbmdcbiAgICAgICAgaWYgKGNsb3NlZCAmJiBzbGljZVswXSAhPT0gc2xpY2Vbc2xpY2UubGVuZ3RoIC0gMV0pIHNsaWNlLnB1c2goc2xpY2VbMF0pO1xuXG4gICAgICAgIC8vIGFkZCB0aGUgZmluYWwgc2xpY2VcbiAgICAgICAgbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWNlcztcbn1cblxuZnVuY3Rpb24gbmV3U2xpY2Uoc2xpY2VzLCBzbGljZSwgYXJlYSwgZGlzdCkge1xuICAgIGlmIChzbGljZS5sZW5ndGgpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3QgcmVjYWxjdWxhdGUgdGhlIGFyZWEvbGVuZ3RoIG9mIHRoZSB1bmNsaXBwZWQgZ2VvbWV0cnkgYmVjYXVzZSB0aGUgY2FzZSB3aGVyZSBpdCBnb2VzXG4gICAgICAgIC8vIGJlbG93IHRoZSB2aXNpYmlsaXR5IHRocmVzaG9sZCBhcyBhIHJlc3VsdCBvZiBjbGlwcGluZyBpcyByYXJlLCBzbyB3ZSBhdm9pZCBkb2luZyB1bm5lY2Vzc2FyeSB3b3JrXG4gICAgICAgIHNsaWNlLmFyZWEgPSBhcmVhO1xuICAgICAgICBzbGljZS5kaXN0ID0gZGlzdDtcblxuICAgICAgICBzbGljZXMucHVzaChzbGljZSk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXJ0O1xuXG52YXIgc2ltcGxpZnkgPSByZXF1aXJlKCcuL3NpbXBsaWZ5Jyk7XG5cbi8vIGNvbnZlcnRzIEdlb0pTT04gZmVhdHVyZSBpbnRvIGFuIGludGVybWVkaWF0ZSBwcm9qZWN0ZWQgSlNPTiB2ZWN0b3IgZm9ybWF0IHdpdGggc2ltcGxpZmljYXRpb24gZGF0YVxuXG5mdW5jdGlvbiBjb252ZXJ0KGRhdGEsIHRvbGVyYW5jZSkge1xuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuXG4gICAgaWYgKGRhdGEudHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEuZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnZlcnRGZWF0dXJlKGZlYXR1cmVzLCBkYXRhLmZlYXR1cmVzW2ldLCB0b2xlcmFuY2UpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdGZWF0dXJlJykge1xuICAgICAgICBjb252ZXJ0RmVhdHVyZShmZWF0dXJlcywgZGF0YSwgdG9sZXJhbmNlKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNpbmdsZSBnZW9tZXRyeSBvciBhIGdlb21ldHJ5IGNvbGxlY3Rpb25cbiAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtnZW9tZXRyeTogZGF0YX0sIHRvbGVyYW5jZSk7XG4gICAgfVxuICAgIHJldHVybiBmZWF0dXJlcztcbn1cblxuZnVuY3Rpb24gY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIGZlYXR1cmUsIHRvbGVyYW5jZSkge1xuICAgIHZhciBnZW9tID0gZmVhdHVyZS5nZW9tZXRyeSxcbiAgICAgICAgdHlwZSA9IGdlb20udHlwZSxcbiAgICAgICAgY29vcmRzID0gZ2VvbS5jb29yZGluYXRlcyxcbiAgICAgICAgdGFncyA9IGZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgaSwgaiwgcmluZ3M7XG5cbiAgICBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBbcHJvamVjdFBvaW50KGNvb3JkcyldKSk7XG5cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdNdWx0aVBvaW50Jykge1xuICAgICAgICBmZWF0dXJlcy5wdXNoKGNyZWF0ZSh0YWdzLCAxLCBwcm9qZWN0KGNvb3JkcykpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0xpbmVTdHJpbmcnKSB7XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIDIsIFtwcm9qZWN0KGNvb3JkcywgdG9sZXJhbmNlKV0pKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ011bHRpTGluZVN0cmluZycgfHwgdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIHJpbmdzID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb29yZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmdzLnB1c2gocHJvamVjdChjb29yZHNbaV0sIHRvbGVyYW5jZSkpO1xuICAgICAgICB9XG4gICAgICAgIGZlYXR1cmVzLnB1c2goY3JlYXRlKHRhZ3MsIHR5cGUgPT09ICdQb2x5Z29uJyA/IDMgOiAyLCByaW5ncykpO1xuXG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTXVsdGlQb2x5Z29uJykge1xuICAgICAgICByaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgY29vcmRzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmluZ3MucHVzaChwcm9qZWN0KGNvb3Jkc1tpXVtqXSwgdG9sZXJhbmNlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmVhdHVyZXMucHVzaChjcmVhdGUodGFncywgMywgcmluZ3MpKTtcblxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20uZ2VvbWV0cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udmVydEZlYXR1cmUoZmVhdHVyZXMsIHtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeTogZ2VvbS5nZW9tZXRyaWVzW2ldLFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHRhZ3NcbiAgICAgICAgICAgIH0sIHRvbGVyYW5jZSk7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVW5zdXBwb3J0ZWQgR2VvSlNPTiB0eXBlOiAnICsgZ2VvbS50eXBlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZSh0YWdzLCB0eXBlLCBnZW9tZXRyeSkge1xuICAgIHZhciBmZWF0dXJlID0ge1xuICAgICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIHRhZ3M6IHRhZ3MgfHwgbnVsbCxcbiAgICAgICAgbWluOiBbMSwgMV0sIC8vIGluaXRpYWwgYmJveCB2YWx1ZXM7XG4gICAgICAgIG1heDogWzAsIDBdICAvLyBub3RlIHRoYXQgYWxsIGNvb3JkcyBhcmUgaW4gWzAuLjFdIHJhbmdlXG4gICAgfTtcbiAgICBjYWxjQkJveChmZWF0dXJlKTtcbiAgICByZXR1cm4gZmVhdHVyZTtcbn1cblxuZnVuY3Rpb24gcHJvamVjdChsb25sYXRzLCB0b2xlcmFuY2UpIHtcbiAgICB2YXIgcHJvamVjdGVkID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb25sYXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByb2plY3RlZC5wdXNoKHByb2plY3RQb2ludChsb25sYXRzW2ldKSk7XG4gICAgfVxuICAgIGlmICh0b2xlcmFuY2UpIHtcbiAgICAgICAgc2ltcGxpZnkocHJvamVjdGVkLCB0b2xlcmFuY2UpO1xuICAgICAgICBjYWxjU2l6ZShwcm9qZWN0ZWQpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvamVjdGVkO1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0UG9pbnQocCkge1xuICAgIHZhciBzaW4gPSBNYXRoLnNpbihwWzFdICogTWF0aC5QSSAvIDE4MCksXG4gICAgICAgIHggPSAocFswXSAvIDM2MCArIDAuNSksXG4gICAgICAgIHkgPSAoMC41IC0gMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyBNYXRoLlBJKTtcbiAgICByZXR1cm4gW3gsIHksIDBdO1xufVxuXG4vLyBjYWxjdWxhdGUgYXJlYSBhbmQgbGVuZ3RoIG9mIHRoZSBwb2x5XG5mdW5jdGlvbiBjYWxjU2l6ZShwb2ludHMpIHtcbiAgICB2YXIgYXJlYSA9IDAsXG4gICAgICAgIGRpc3QgPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGEsIGI7IGkgPCBwb2ludHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGEgPSBiIHx8IHBvaW50c1tpXTtcbiAgICAgICAgYiA9IHBvaW50c1tpICsgMV07XG5cbiAgICAgICAgYXJlYSArPSBhWzBdICogYlsxXSAtIGJbMF0gKiBhWzFdO1xuXG4gICAgICAgIC8vIHVzZSBNYW5oYXR0YW4gZGlzdGFuY2UgaW5zdGVhZCBvZiBFdWNsaWRpYW4gb25lIHRvIGF2b2lkIGV4cGVuc2l2ZSBzcXVhcmUgcm9vdCBjb21wdXRhdGlvblxuICAgICAgICBkaXN0ICs9IE1hdGguYWJzKGJbMF0gLSBhWzBdKSArIE1hdGguYWJzKGJbMV0gLSBhWzFdKTtcbiAgICB9XG4gICAgcG9pbnRzLmFyZWEgPSBNYXRoLmFicyhhcmVhIC8gMik7XG4gICAgcG9pbnRzLmRpc3QgPSBkaXN0O1xufVxuXG4vLyBjYWxjdWxhdGUgdGhlIGZlYXR1cmUgYm91bmRpbmcgYm94IGZvciBmYXN0ZXIgY2xpcHBpbmcgbGF0ZXJcbmZ1bmN0aW9uIGNhbGNCQm94KGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5LFxuICAgICAgICBtaW4gPSBmZWF0dXJlLm1pbixcbiAgICAgICAgbWF4ID0gZmVhdHVyZS5tYXg7XG5cbiAgICBpZiAoZmVhdHVyZS50eXBlID09PSAxKSBjYWxjUmluZ0JCb3gobWluLCBtYXgsIGdlb21ldHJ5KTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvbWV0cnkubGVuZ3RoOyBpKyspIGNhbGNSaW5nQkJveChtaW4sIG1heCwgZ2VvbWV0cnlbaV0pO1xuXG4gICAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGNhbGNSaW5nQkJveChtaW4sIG1heCwgcG9pbnRzKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcCA9IHBvaW50c1tpXTtcbiAgICAgICAgbWluWzBdID0gTWF0aC5taW4ocFswXSwgbWluWzBdKTtcbiAgICAgICAgbWF4WzBdID0gTWF0aC5tYXgocFswXSwgbWF4WzBdKTtcbiAgICAgICAgbWluWzFdID0gTWF0aC5taW4ocFsxXSwgbWluWzFdKTtcbiAgICAgICAgbWF4WzFdID0gTWF0aC5tYXgocFsxXSwgbWF4WzFdKTtcbiAgICB9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZ2VvanNvbnZ0O1xuXG52YXIgY29udmVydCA9IHJlcXVpcmUoJy4vY29udmVydCcpLCAvLyBHZW9KU09OIGNvbnZlcnNpb24gYW5kIHByZXByb2Nlc3NpbmdcbiAgICBjbGlwID0gcmVxdWlyZSgnLi9jbGlwJyksICAgICAgIC8vIHN0cmlwZSBjbGlwcGluZyBhbGdvcml0aG1cbiAgICBjcmVhdGVUaWxlID0gcmVxdWlyZSgnLi90aWxlJyk7IC8vIGZpbmFsIHNpbXBsaWZpZWQgdGlsZSBnZW5lcmF0aW9uXG5cblxuZnVuY3Rpb24gZ2VvanNvbnZ0KGRhdGEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IEdlb0pTT05WVChkYXRhLCBvcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gR2VvSlNPTlZUKGRhdGEsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zID0gZXh0ZW5kKE9iamVjdC5jcmVhdGUodGhpcy5vcHRpb25zKSwgb3B0aW9ucyk7XG5cbiAgICB2YXIgZGVidWcgPSBvcHRpb25zLmRlYnVnO1xuXG4gICAgaWYgKGRlYnVnKSBjb25zb2xlLnRpbWUoJ3ByZXByb2Nlc3MgZGF0YScpO1xuXG4gICAgdmFyIHoyID0gMSA8PCBvcHRpb25zLmJhc2Vab29tLCAvLyAyXnpcbiAgICAgICAgZmVhdHVyZXMgPSBjb252ZXJ0KGRhdGEsIG9wdGlvbnMudG9sZXJhbmNlIC8gKHoyICogb3B0aW9ucy5leHRlbnQpKTtcblxuICAgIHRoaXMudGlsZXMgPSB7fTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoJ3ByZXByb2Nlc3MgZGF0YScpO1xuICAgICAgICBjb25zb2xlLnRpbWUoJ2dlbmVyYXRlIHRpbGVzIHVwIHRvIHonICsgb3B0aW9ucy5tYXhab29tKTtcbiAgICAgICAgdGhpcy5zdGF0cyA9IHt9O1xuICAgICAgICB0aGlzLnRvdGFsID0gMDtcbiAgICB9XG5cbiAgICAvLyBzdGFydCBzbGljaW5nIGZyb20gdGhlIHRvcCB0aWxlIGRvd25cbiAgICB0aGlzLnNwbGl0VGlsZShmZWF0dXJlcywgMCwgMCwgMCk7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2ZlYXR1cmVzOiAlZCwgcG9pbnRzOiAlZCcsIHRoaXMudGlsZXNbMF0ubnVtRmVhdHVyZXMsIHRoaXMudGlsZXNbMF0ubnVtUG9pbnRzKTtcbiAgICAgICAgY29uc29sZS50aW1lRW5kKCdnZW5lcmF0ZSB0aWxlcyB1cCB0byB6JyArIG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCd0aWxlcyBnZW5lcmF0ZWQ6JywgdGhpcy50b3RhbCwgSlNPTi5zdHJpbmdpZnkodGhpcy5zdGF0cykpO1xuICAgIH1cbn1cblxuR2VvSlNPTlZULnByb3RvdHlwZS5vcHRpb25zID0ge1xuICAgIGJhc2Vab29tOiAxNCwgICAvLyBtYXggem9vbSB0byBwcmVzZXJ2ZSBkZXRhaWwgb25cbiAgICBtYXhab29tOiA0LCAgICAgLy8gem9vbSB0byBzbGljZSBkb3duIHRvIG9uIGZpcnN0IHBhc3NcbiAgICBtYXhQb2ludHM6IDEwMCwgLy8gc3RvcCBzbGljaW5nIGEgdGlsZSBiZWxvdyB0aGlzIG51bWJlciBvZiBwb2ludHNcbiAgICB0b2xlcmFuY2U6IDMsICAgLy8gc2ltcGxpZmljYXRpb24gdG9sZXJhbmNlIChoaWdoZXIgbWVhbnMgc2ltcGxlcilcbiAgICBleHRlbnQ6IDQwOTYsICAgLy8gdGlsZSBleHRlbnRcbiAgICBidWZmZXI6IDY0LCAgICAgLy8gdGlsZSBidWZmZXIgb24gZWFjaCBzaWRlXG4gICAgZGVidWc6IDAgICAgICAgIC8vIGxvZ2dpbmcgbGV2ZWwgKDAsIDEgb3IgMilcbn07XG5cbkdlb0pTT05WVC5wcm90b3R5cGUuc3BsaXRUaWxlID0gZnVuY3Rpb24gKGZlYXR1cmVzLCB6LCB4LCB5LCBjeiwgY3gsIGN5KSB7XG5cbiAgICB2YXIgc3RhY2sgPSBbZmVhdHVyZXMsIHosIHgsIHldLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICBkZWJ1ZyA9IG9wdGlvbnMuZGVidWcsXG4gICAgICAgIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50LFxuICAgICAgICBidWZmZXIgPSBvcHRpb25zLmJ1ZmZlcjtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHByb2Nlc3NpbmcgcXVldWVcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoKSB7XG4gICAgICAgIGZlYXR1cmVzID0gc3RhY2suc2hpZnQoKTtcbiAgICAgICAgeiA9IHN0YWNrLnNoaWZ0KCk7XG4gICAgICAgIHggPSBzdGFjay5zaGlmdCgpO1xuICAgICAgICB5ID0gc3RhY2suc2hpZnQoKTtcblxuICAgICAgICB2YXIgejIgPSAxIDw8IHosXG4gICAgICAgICAgICBpZCA9IHRvSUQoeiwgeCwgeSksXG4gICAgICAgICAgICB0aWxlID0gdGhpcy50aWxlc1tpZF0sXG4gICAgICAgICAgICB0aWxlVG9sZXJhbmNlID0geiA9PT0gb3B0aW9ucy5iYXNlWm9vbSA/IDAgOiBvcHRpb25zLnRvbGVyYW5jZSAvICh6MiAqIGV4dGVudCk7XG5cbiAgICAgICAgaWYgKCF0aWxlKSB7XG4gICAgICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NyZWF0aW9uJyk7XG5cbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLnRpbGVzW2lkXSA9IGNyZWF0ZVRpbGUoZmVhdHVyZXMsIHoyLCB4LCB5LCB0aWxlVG9sZXJhbmNlLCBleHRlbnQsIHogPT09IG9wdGlvbnMuYmFzZVpvb20pO1xuXG4gICAgICAgICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVidWcgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCd0aWxlIHolZC0lZC0lZCAoZmVhdHVyZXM6ICVkLCBwb2ludHM6ICVkLCBzaW1wbGlmaWVkOiAlZCknLFxuICAgICAgICAgICAgICAgICAgICAgICAgeiwgeCwgeSwgdGlsZS5udW1GZWF0dXJlcywgdGlsZS5udW1Qb2ludHMsIHRpbGUubnVtU2ltcGxpZmllZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZCgnY3JlYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICd6JyArIHogKyAnOic7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0c1trZXldID0gKHRoaXMuc3RhdHNba2V5XSB8fCAwKSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy50b3RhbCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjeiAmJiAoeiA9PT0gb3B0aW9ucy5tYXhab29tIHx8IHRpbGUubnVtUG9pbnRzIDw9IG9wdGlvbnMubWF4UG9pbnRzIHx8XG4gICAgICAgICAgICAgICAgaXNDbGlwcGVkU3F1YXJlKHRpbGUuZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSkgfHwgeiA9PT0gb3B0aW9ucy5iYXNlWm9vbSB8fCB6ID09PSBjeikge1xuICAgICAgICAgICAgdGlsZS5zb3VyY2UgPSBmZWF0dXJlcztcbiAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBzdG9wIHRpbGluZ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN6KSB0aWxlLnNvdXJjZSA9IGZlYXR1cmVzO1xuICAgICAgICBlbHNlIHRpbGUuc291cmNlID0gbnVsbDtcblxuICAgICAgICBpZiAoZGVidWcgPiAxKSBjb25zb2xlLnRpbWUoJ2NsaXBwaW5nJyk7XG5cbiAgICAgICAgLy8gdmFsdWVzIHdlJ2xsIHVzZSBmb3IgY2xpcHBpbmdcbiAgICAgICAgdmFyIGsxID0gMC41ICogYnVmZmVyIC8gZXh0ZW50LFxuICAgICAgICAgICAgazIgPSAwLjUgLSBrMSxcbiAgICAgICAgICAgIGszID0gMC41ICsgazEsXG4gICAgICAgICAgICBrNCA9IDEgKyBrMSxcblxuICAgICAgICAgICAgdGwsIGJsLCB0ciwgYnIsIGxlZnQsIHJpZ2h0LFxuICAgICAgICAgICAgbSwgZ29MZWZ0LCBnb1RvcDtcblxuICAgICAgICBpZiAoY3opIHsgLy8gaWYgd2UgaGF2ZSBhIHNwZWNpZmljIHRpbGUgdG8gZHJpbGwgZG93biB0bywgY2FsY3VsYXRlIHdoZXJlIHRvIGdvXG4gICAgICAgICAgICBtID0gMSA8PCAoY3ogLSB6KTtcbiAgICAgICAgICAgIGdvTGVmdCA9IGN4IC8gbSAtIHggPCAwLjU7XG4gICAgICAgICAgICBnb1RvcCA9IGN5IC8gbSAtIHkgPCAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICB0bCA9IGJsID0gdHIgPSBiciA9IGxlZnQgPSByaWdodCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCFjeiB8fCAgZ29MZWZ0KSBsZWZ0ICA9IGNsaXAoZmVhdHVyZXMsIHoyLCB4IC0gazEsIHggKyBrMywgMCwgaW50ZXJzZWN0WCk7XG4gICAgICAgIGlmICghY3ogfHwgIWdvTGVmdCkgcmlnaHQgPSBjbGlwKGZlYXR1cmVzLCB6MiwgeCArIGsyLCB4ICsgazQsIDAsIGludGVyc2VjdFgpO1xuXG4gICAgICAgIGlmIChsZWZ0KSB7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICBnb1RvcCkgdGwgPSBjbGlwKGxlZnQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYmwgPSBjbGlwKGxlZnQsIHoyLCB5ICsgazIsIHkgKyBrNCwgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgIGlmICghY3ogfHwgIGdvVG9wKSB0ciA9IGNsaXAocmlnaHQsIHoyLCB5IC0gazEsIHkgKyBrMywgMSwgaW50ZXJzZWN0WSk7XG4gICAgICAgICAgICBpZiAoIWN6IHx8ICFnb1RvcCkgYnIgPSBjbGlwKHJpZ2h0LCB6MiwgeSArIGsyLCB5ICsgazQsIDEsIGludGVyc2VjdFkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS50aW1lRW5kKCdjbGlwcGluZycpO1xuXG4gICAgICAgIGlmICh0bCkgc3RhY2sucHVzaCh0bCwgeiArIDEsIHggKiAyLCAgICAgeSAqIDIpO1xuICAgICAgICBpZiAoYmwpIHN0YWNrLnB1c2goYmwsIHogKyAxLCB4ICogMiwgICAgIHkgKiAyICsgMSk7XG4gICAgICAgIGlmICh0cikgc3RhY2sucHVzaCh0ciwgeiArIDEsIHggKiAyICsgMSwgeSAqIDIpO1xuICAgICAgICBpZiAoYnIpIHN0YWNrLnB1c2goYnIsIHogKyAxLCB4ICogMiArIDEsIHkgKiAyICsgMSk7XG4gICAgfVxufTtcblxuR2VvSlNPTlZULnByb3RvdHlwZS5nZXRUaWxlID0gZnVuY3Rpb24gKHosIHgsIHkpIHtcbiAgICB2YXIgaWQgPSB0b0lEKHosIHgsIHkpO1xuICAgIGlmICh0aGlzLnRpbGVzW2lkXSkgcmV0dXJuIHRoaXMudGlsZXNbaWRdO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgIGRlYnVnID0gb3B0aW9ucy5kZWJ1ZztcblxuICAgIGlmIChkZWJ1ZyA+IDEpIGNvbnNvbGUubG9nKCdkcmlsbGluZyBkb3duIHRvIHolZC0lZC0lZCcsIHosIHgsIHkpO1xuXG4gICAgdmFyIHowID0geixcbiAgICAgICAgeDAgPSB4LFxuICAgICAgICB5MCA9IHksXG4gICAgICAgIHBhcmVudDtcblxuICAgIHdoaWxlICghcGFyZW50ICYmIHowID4gMCkge1xuICAgICAgICB6MC0tO1xuICAgICAgICB4MCA9IE1hdGguZmxvb3IoeDAgLyAyKTtcbiAgICAgICAgeTAgPSBNYXRoLmZsb29yKHkwIC8gMik7XG4gICAgICAgIHBhcmVudCA9IHRoaXMudGlsZXNbdG9JRCh6MCwgeDAsIHkwKV07XG4gICAgfVxuXG4gICAgaWYgKGRlYnVnID4gMSkgY29uc29sZS5sb2coJ2ZvdW5kIHBhcmVudCB0aWxlIHolZC0lZC0lZCcsIHowLCB4MCwgeTApO1xuXG4gICAgLy8gaWYgd2UgZm91bmQgYSBwYXJlbnQgdGlsZSBjb250YWluaW5nIHRoZSBvcmlnaW5hbCBnZW9tZXRyeSwgd2UgY2FuIGRyaWxsIGRvd24gZnJvbSBpdFxuICAgIGlmIChwYXJlbnQuc291cmNlKSB7XG4gICAgICAgIGlmIChpc0NsaXBwZWRTcXVhcmUocGFyZW50LmZlYXR1cmVzLCBvcHRpb25zLmV4dGVudCwgb3B0aW9ucy5idWZmZXIpKSByZXR1cm4gcGFyZW50O1xuXG4gICAgICAgIGlmIChkZWJ1ZykgY29uc29sZS50aW1lKCdkcmlsbGluZyBkb3duJyk7XG4gICAgICAgIHRoaXMuc3BsaXRUaWxlKHBhcmVudC5zb3VyY2UsIHowLCB4MCwgeTAsIHosIHgsIHkpO1xuICAgICAgICBpZiAoZGVidWcpIGNvbnNvbGUudGltZUVuZCgnZHJpbGxpbmcgZG93bicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRpbGVzW2lkXTtcbn07XG5cbi8vIGNoZWNrcyB3aGV0aGVyIGEgdGlsZSBpcyBhIHdob2xlLWFyZWEgZmlsbCBhZnRlciBjbGlwcGluZzsgaWYgaXQgaXMsIHRoZXJlJ3Mgbm8gc2Vuc2Ugc2xpY2luZyBpdCBmdXJ0aGVyXG5mdW5jdGlvbiBpc0NsaXBwZWRTcXVhcmUoZmVhdHVyZXMsIGV4dGVudCwgYnVmZmVyKSB7XG4gICAgaWYgKGZlYXR1cmVzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGZlYXR1cmUgPSBmZWF0dXJlc1swXTtcbiAgICBpZiAoZmVhdHVyZS50eXBlICE9PSAzIHx8IGZlYXR1cmUuZ2VvbWV0cnkubGVuZ3RoID4gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmZWF0dXJlLmdlb21ldHJ5WzBdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwID0gZmVhdHVyZS5nZW9tZXRyeVswXVtpXTtcbiAgICAgICAgaWYgKChwWzBdICE9PSAtYnVmZmVyICYmIHBbMF0gIT09IGV4dGVudCArIGJ1ZmZlcikgfHxcbiAgICAgICAgICAgIChwWzFdICE9PSAtYnVmZmVyICYmIHBbMV0gIT09IGV4dGVudCArIGJ1ZmZlcikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHRvSUQoeiwgeCwgeSkge1xuICAgIHJldHVybiAoKCgxIDw8IHopICogeSArIHgpICogMzIpICsgejtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0WChhLCBiLCB4KSB7XG4gICAgcmV0dXJuIFt4LCAoeCAtIGFbMF0pICogKGJbMV0gLSBhWzFdKSAvIChiWzBdIC0gYVswXSkgKyBhWzFdLCAxXTtcbn1cbmZ1bmN0aW9uIGludGVyc2VjdFkoYSwgYiwgeSkge1xuICAgIHJldHVybiBbKHkgLSBhWzFdKSAqIChiWzBdIC0gYVswXSkgLyAoYlsxXSAtIGFbMV0pICsgYVswXSwgeSwgMV07XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMpIHtcbiAgICBmb3IgKHZhciBpIGluIHNyYykgZGVzdFtpXSA9IHNyY1tpXTtcbiAgICByZXR1cm4gZGVzdDtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBzaW1wbGlmeTtcblxuLy8gY2FsY3VsYXRlIHNpbXBsaWZpY2F0aW9uIGRhdGEgdXNpbmcgb3B0aW1pemVkIERvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1cblxuZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcblxuICAgIHZhciBzcVRvbGVyYW5jZSA9IHRvbGVyYW5jZSAqIHRvbGVyYW5jZSxcbiAgICAgICAgbGVuID0gcG9pbnRzLmxlbmd0aCxcbiAgICAgICAgZmlyc3QgPSAwLFxuICAgICAgICBsYXN0ID0gbGVuIC0gMSxcbiAgICAgICAgc3RhY2sgPSBbXSxcbiAgICAgICAgaSwgbWF4U3FEaXN0LCBzcURpc3QsIGluZGV4O1xuXG4gICAgLy8gYWx3YXlzIHJldGFpbiB0aGUgZW5kcG9pbnRzICgxIGlzIHRoZSBtYXggdmFsdWUpXG4gICAgcG9pbnRzW2ZpcnN0XVsyXSA9IDE7XG4gICAgcG9pbnRzW2xhc3RdWzJdID0gMTtcblxuICAgIC8vIGF2b2lkIHJlY3Vyc2lvbiBieSB1c2luZyBhIHN0YWNrXG4gICAgd2hpbGUgKGxhc3QpIHtcblxuICAgICAgICBtYXhTcURpc3QgPSAwO1xuXG4gICAgICAgIGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgc3FEaXN0ID0gZ2V0U3FTZWdEaXN0KHBvaW50c1tpXSwgcG9pbnRzW2ZpcnN0XSwgcG9pbnRzW2xhc3RdKTtcblxuICAgICAgICAgICAgaWYgKHNxRGlzdCA+IG1heFNxRGlzdCkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBtYXhTcURpc3QgPSBzcURpc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4U3FEaXN0ID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgIHBvaW50c1tpbmRleF1bMl0gPSBtYXhTcURpc3Q7IC8vIHNhdmUgdGhlIHBvaW50IGltcG9ydGFuY2UgaW4gc3F1YXJlZCBwaXhlbHMgYXMgYSB6IGNvb3JkaW5hdGVcbiAgICAgICAgICAgIHN0YWNrLnB1c2goZmlyc3QsIGluZGV4LCBpbmRleCwgbGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXN0ID0gc3RhY2sucG9wKCk7XG4gICAgICAgIGZpcnN0ID0gc3RhY2sucG9wKCk7XG4gICAgfVxufVxuXG4vLyBzcXVhcmUgZGlzdGFuY2UgZnJvbSBhIHBvaW50IHRvIGEgc2VnbWVudFxuZnVuY3Rpb24gZ2V0U3FTZWdEaXN0KHAsIGEsIGIpIHtcblxuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sXG4gICAgICAgIGJ4ID0gYlswXSwgYnkgPSBiWzFdLFxuICAgICAgICBweCA9IHBbMF0sIHB5ID0gcFsxXSxcbiAgICAgICAgZHggPSBieCAtIHgsXG4gICAgICAgIGR5ID0gYnkgLSB5O1xuXG4gICAgaWYgKGR4ICE9PSAwIHx8IGR5ICE9PSAwKSB7XG5cbiAgICAgICAgdmFyIHQgPSAoKHB4IC0geCkgKiBkeCArIChweSAtIHkpICogZHkpIC8gKGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZiAodCA+IDEpIHtcbiAgICAgICAgICAgIHggPSBieDtcbiAgICAgICAgICAgIHkgPSBieTtcblxuICAgICAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICAgICAgICB4ICs9IGR4ICogdDtcbiAgICAgICAgICAgIHkgKz0gZHkgKiB0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHggPSBweCAtIHg7XG4gICAgZHkgPSBweSAtIHk7XG5cbiAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGlsZTtcblxuZnVuY3Rpb24gY3JlYXRlVGlsZShmZWF0dXJlcywgejIsIHR4LCB0eSwgdG9sZXJhbmNlLCBleHRlbnQsIG5vU2ltcGxpZnkpIHtcbiAgICB2YXIgdGlsZSA9IHtcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgICBudW1Qb2ludHM6IDAsXG4gICAgICAgIG51bVNpbXBsaWZpZWQ6IDAsXG4gICAgICAgIG51bUZlYXR1cmVzOiAwLFxuICAgICAgICBzb3VyY2U6IG51bGxcbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGlsZS5udW1GZWF0dXJlcysrO1xuICAgICAgICBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmVzW2ldLCB6MiwgdHgsIHR5LCB0b2xlcmFuY2UsIGV4dGVudCwgbm9TaW1wbGlmeSk7XG4gICAgfVxuICAgIHJldHVybiB0aWxlO1xufVxuXG5mdW5jdGlvbiBhZGRGZWF0dXJlKHRpbGUsIGZlYXR1cmUsIHoyLCB0eCwgdHksIHRvbGVyYW5jZSwgZXh0ZW50LCBub1NpbXBsaWZ5KSB7XG5cbiAgICB2YXIgZ2VvbSA9IGZlYXR1cmUuZ2VvbWV0cnksXG4gICAgICAgIHR5cGUgPSBmZWF0dXJlLnR5cGUsXG4gICAgICAgIHRyYW5zZm9ybWVkID0gW10sXG4gICAgICAgIHNxVG9sZXJhbmNlID0gdG9sZXJhbmNlICogdG9sZXJhbmNlLFxuICAgICAgICBpLCBqLCByaW5nLCBwO1xuXG4gICAgaWYgKHR5cGUgPT09IDEpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWVkLnB1c2godHJhbnNmb3JtUG9pbnQoZ2VvbVtpXSwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgdGlsZS5udW1TaW1wbGlmaWVkKys7XG4gICAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gc2ltcGxpZnkgYW5kIHRyYW5zZm9ybSBwcm9qZWN0ZWQgY29vcmRpbmF0ZXMgZm9yIHRpbGUgZ2VvbWV0cnlcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdlb20ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJpbmcgPSBnZW9tW2ldO1xuXG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHRpbnkgcG9seWxpbmVzICYgcG9seWdvbnNcbiAgICAgICAgICAgIGlmICghbm9TaW1wbGlmeSAmJiAoKHR5cGUgPT09IDIgJiYgcmluZy5kaXN0IDwgdG9sZXJhbmNlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodHlwZSA9PT0gMyAmJiByaW5nLmFyZWEgPCBzcVRvbGVyYW5jZSkpKSB7XG4gICAgICAgICAgICAgICAgdGlsZS5udW1Qb2ludHMgKz0gcmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1lZFJpbmcgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHJpbmcubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcmluZ1tqXTtcbiAgICAgICAgICAgICAgICAvLyBrZWVwIHBvaW50cyB3aXRoIGltcG9ydGFuY2UgPiB0b2xlcmFuY2VcbiAgICAgICAgICAgICAgICBpZiAobm9TaW1wbGlmeSB8fCBwWzJdID4gc3FUb2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRSaW5nLnB1c2godHJhbnNmb3JtUG9pbnQocCwgejIsIHR4LCB0eSwgZXh0ZW50KSk7XG4gICAgICAgICAgICAgICAgICAgIHRpbGUubnVtU2ltcGxpZmllZCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aWxlLm51bVBvaW50cysrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cmFuc2Zvcm1lZC5wdXNoKHRyYW5zZm9ybWVkUmluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNmb3JtZWQubGVuZ3RoKSB7XG4gICAgICAgIHRpbGUuZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICBnZW9tZXRyeTogdHJhbnNmb3JtZWQsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgdGFnczogZmVhdHVyZS50YWdzIHx8IG51bGxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludChwLCB6MiwgdHgsIHR5LCBleHRlbnQpIHtcbiAgICB2YXIgeCA9IE1hdGgucm91bmQoZXh0ZW50ICogKHBbMF0gKiB6MiAtIHR4KSksXG4gICAgICAgIHkgPSBNYXRoLnJvdW5kKGV4dGVudCAqIChwWzFdICogejIgLSB0eSkpO1xuICAgIHJldHVybiBbeCwgeV07XG59XG4iLCIvKipcbiAqIEBmaWxlb3ZlcnZpZXcgZ2wtbWF0cml4IC0gSGlnaCBwZXJmb3JtYW5jZSBtYXRyaXggYW5kIHZlY3RvciBvcGVyYXRpb25zXG4gKiBAYXV0aG9yIEJyYW5kb24gSm9uZXNcbiAqIEBhdXRob3IgQ29saW4gTWFjS2VuemllIElWXG4gKiBAdmVyc2lvbiAyLjIuMVxuICovXG5cbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbihmdW5jdGlvbihfZ2xvYmFsKSB7XG4gIFwidXNlIHN0cmljdFwiO1xuXG4gIHZhciBzaGltID0ge307XG4gIGlmICh0eXBlb2YoZXhwb3J0cykgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHt9O1xuICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gc2hpbS5leHBvcnRzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBhIGJyb3dzZXIsIGRlZmluZSBpdHMgbmFtZXNwYWNlcyBpbiBnbG9iYWxcbiAgICAgIHNoaW0uZXhwb3J0cyA9IHR5cGVvZih3aW5kb3cpICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IF9nbG9iYWw7XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIC8vIGdsLW1hdHJpeCBsaXZlcyBpbiBjb21tb25qcywgZGVmaW5lIGl0cyBuYW1lc3BhY2VzIGluIGV4cG9ydHNcbiAgICBzaGltLmV4cG9ydHMgPSBleHBvcnRzO1xuICB9XG5cbiAgKGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAvKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG5cbmlmKCFHTE1BVF9FUFNJTE9OKSB7XG4gICAgdmFyIEdMTUFUX0VQU0lMT04gPSAwLjAwMDAwMTtcbn1cblxuaWYoIUdMTUFUX0FSUkFZX1RZUEUpIHtcbiAgICB2YXIgR0xNQVRfQVJSQVlfVFlQRSA9ICh0eXBlb2YgRmxvYXQzMkFycmF5ICE9PSAndW5kZWZpbmVkJykgPyBGbG9hdDMyQXJyYXkgOiBBcnJheTtcbn1cblxuaWYoIUdMTUFUX1JBTkRPTSkge1xuICAgIHZhciBHTE1BVF9SQU5ET00gPSBNYXRoLnJhbmRvbTtcbn1cblxuLyoqXG4gKiBAY2xhc3MgQ29tbW9uIHV0aWxpdGllc1xuICogQG5hbWUgZ2xNYXRyaXhcbiAqL1xudmFyIGdsTWF0cml4ID0ge307XG5cbi8qKlxuICogU2V0cyB0aGUgdHlwZSBvZiBhcnJheSB1c2VkIHdoZW4gY3JlYXRpbmcgbmV3IHZlY3RvcnMgYW5kIG1hdHJpY2llc1xuICpcbiAqIEBwYXJhbSB7VHlwZX0gdHlwZSBBcnJheSB0eXBlLCBzdWNoIGFzIEZsb2F0MzJBcnJheSBvciBBcnJheVxuICovXG5nbE1hdHJpeC5zZXRNYXRyaXhBcnJheVR5cGUgPSBmdW5jdGlvbih0eXBlKSB7XG4gICAgR0xNQVRfQVJSQVlfVFlQRSA9IHR5cGU7XG59XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLmdsTWF0cml4ID0gZ2xNYXRyaXg7XG59XG5cbnZhciBkZWdyZWUgPSBNYXRoLlBJIC8gMTgwO1xuXG4vKipcbiogQ29udmVydCBEZWdyZWUgVG8gUmFkaWFuXG4qXG4qIEBwYXJhbSB7TnVtYmVyfSBBbmdsZSBpbiBEZWdyZWVzXG4qL1xuZ2xNYXRyaXgudG9SYWRpYW4gPSBmdW5jdGlvbihhKXtcbiAgICAgcmV0dXJuIGEgKiBkZWdyZWU7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyIERpbWVuc2lvbmFsIFZlY3RvclxuICogQG5hbWUgdmVjMlxuICovXG5cbnZhciB2ZWMyID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldywgZW1wdHkgdmVjMlxuICpcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gMDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMik7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMiBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBhIG5ldyAyRCB2ZWN0b3JcbiAqL1xudmVjMi5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgyKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzIgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHkpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLmFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnN1YnRyYWN0ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAtIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnN1YnRyYWN0fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuc3ViID0gdmVjMi5zdWJ0cmFjdDtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICogYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5tdWwgPSB2ZWMyLm11bHRpcGx5O1xuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5kaXZpZGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC8gYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdIC8gYlsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzIuZGl2aWRlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGl2ID0gdmVjMi5kaXZpZGU7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWluaW11bSBvZiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLm1pbiA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pO1xuICAgIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5tYXggPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1heChhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgYSB2ZWMyIGJ5IGEgc2NhbGFyIG51bWJlclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiO1xuICAgIG91dFsxXSA9IGFbMV0gKiBiO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzIncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnNjYWxlQW5kQWRkID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBzY2FsZSkge1xuICAgIG91dFswXSA9IGFbMF0gKyAoYlswXSAqIHNjYWxlKTtcbiAgICBvdXRbMV0gPSBhWzFdICsgKGJbMV0gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzIuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdO1xuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5KTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLmRpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzIuZGlzdCA9IHZlYzIuZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMidzXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG52ZWMyLnNxdWFyZWREaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLnNxckRpc3QgPSB2ZWMyLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMyLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMi5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5sZW4gPSB2ZWMyLmxlbmd0aDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG52ZWMyLnNxdWFyZWRMZW5ndGggPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV07XG4gICAgcmV0dXJuIHgqeCArIHkqeTtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMyLnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjMi5zcXJMZW4gPSB2ZWMyLnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzJcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWMyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzInc1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMyLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV07XG59O1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMyJ3NcbiAqIE5vdGUgdGhhdCB0aGUgY3Jvc3MgcHJvZHVjdCBtdXN0IGJ5IGRlZmluaXRpb24gcHJvZHVjZSBhIDNEIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjMn0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMi5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciB6ID0gYVswXSAqIGJbMV0gLSBhWzFdICogYlswXTtcbiAgICBvdXRbMF0gPSBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IHo7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMyJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzJ9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMyfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzJ9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV07XG4gICAgb3V0WzBdID0gYXggKyB0ICogKGJbMF0gLSBheCk7XG4gICAgb3V0WzFdID0gYXkgKyB0ICogKGJbMV0gLSBheSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi5yYW5kb20gPSBmdW5jdGlvbiAob3V0LCBzY2FsZSkge1xuICAgIHNjYWxlID0gc2NhbGUgfHwgMS4wO1xuICAgIHZhciByID0gR0xNQVRfUkFORE9NKCkgKiAyLjAgKiBNYXRoLlBJO1xuICAgIG91dFswXSA9IE1hdGguY29zKHIpICogc2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiBzY2FsZTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQyfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDIgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHk7XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzNdICogeTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMyIHdpdGggYSBtYXQyZFxuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0MmR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjMn0gb3V0XG4gKi9cbnZlYzIudHJhbnNmb3JtTWF0MmQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDNcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzEnXG4gKlxuICogQHBhcmFtIHt2ZWMyfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjMn0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQzfSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzJ9IG91dFxuICovXG52ZWMyLnRyYW5zZm9ybU1hdDMgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdO1xuICAgIG91dFswXSA9IG1bMF0gKiB4ICsgbVszXSAqIHkgKyBtWzZdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs0XSAqIHkgKyBtWzddO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzIgd2l0aCBhIG1hdDRcbiAqIDNyZCB2ZWN0b3IgY29tcG9uZW50IGlzIGltcGxpY2l0bHkgJzAnXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjMn0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzJ9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMyfSBvdXRcbiAqL1xudmVjMi50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCBcbiAgICAgICAgeSA9IGFbMV07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bMTJdO1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzEzXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjMnMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMi4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzJzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMyLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzIuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjMn0gdmVjIHZlY3RvciB0byByZXByZXNlbnQgYXMgYSBzdHJpbmdcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmVjdG9yXG4gKi9cbnZlYzIuc3RyID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gJ3ZlYzIoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzIgPSB2ZWMyO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgMyBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzNcbiAqL1xuXG52YXIgdmVjMyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbnZlYzMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDMpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMyBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMyk7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xudmVjMy5mcm9tVmFsdWVzID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSgzKTtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjMyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzIHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnNldCA9IGZ1bmN0aW9uKG91dCwgeCwgeSwgeikge1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnN1YiA9IHZlYzMuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubXVsID0gdmVjMy5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpdiA9IHZlYzMuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5kaXN0YW5jZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeik7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmRpc3QgPSB2ZWMzLmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjMy5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl07XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqejtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLnNxdWFyZWREaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckRpc3QgPSB2ZWMzLnNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG52ZWMzLmxlbmd0aCA9IGZ1bmN0aW9uIChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl07XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnopO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzMubGVuID0gdmVjMy5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjMy5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzMuc3F1YXJlZExlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLnNxckxlbiA9IHZlYzMuc3F1YXJlZExlbmd0aDtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLm5lZ2F0ZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IC1hWzBdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5ub3JtYWxpemUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXTtcbiAgICB2YXIgbGVuID0geCp4ICsgeSp5ICsgeip6O1xuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICAgICAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgICAgICAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICovXG52ZWMzLmRvdCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTtcbn07XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy5jcm9zcyA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdO1xuXG4gICAgb3V0WzBdID0gYXkgKiBieiAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMubGVycCA9IGZ1bmN0aW9uIChvdXQsIGEsIGIsIHQpIHtcbiAgICB2YXIgYXggPSBhWzBdLFxuICAgICAgICBheSA9IGFbMV0sXG4gICAgICAgIGF6ID0gYVsyXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICB2YXIgciA9IEdMTUFUX1JBTkRPTSgpICogMi4wICogTWF0aC5QSTtcbiAgICB2YXIgeiA9IChHTE1BVF9SQU5ET00oKSAqIDIuMCkgLSAxLjA7XG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlO1xuXG4gICAgb3V0WzBdID0gTWF0aC5jb3MocikgKiB6U2NhbGU7XG4gICAgb3V0WzFdID0gTWF0aC5zaW4ocikgKiB6U2NhbGU7XG4gICAgb3V0WzJdID0geiAqIHNjYWxlO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xudmVjMy50cmFuc2Zvcm1NYXQ0ID0gZnVuY3Rpb24ob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl07XG4gICAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM107XG4gICAgb3V0WzJdID0gbVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbnZlYzMudHJhbnNmb3JtTWF0MyA9IGZ1bmN0aW9uKG91dCwgYSwgbSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdO1xuICAgIG91dFswXSA9IHggKiBtWzBdICsgeSAqIG1bM10gKyB6ICogbVs2XTtcbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN107XG4gICAgb3V0WzJdID0geCAqIG1bMl0gKyB5ICogbVs1XSArIHogKiBtWzhdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG52ZWMzLnRyYW5zZm9ybVF1YXQgPSBmdW5jdGlvbihvdXQsIGEsIHEpIHtcbiAgICAvLyBiZW5jaG1hcmtzOiBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXRyYW5zZm9ybS12ZWMzLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl0sXG4gICAgICAgIHF4ID0gcVswXSwgcXkgPSBxWzFdLCBxeiA9IHFbMl0sIHF3ID0gcVszXSxcblxuICAgICAgICAvLyBjYWxjdWxhdGUgcXVhdCAqIHZlY1xuICAgICAgICBpeCA9IHF3ICogeCArIHF5ICogeiAtIHF6ICogeSxcbiAgICAgICAgaXkgPSBxdyAqIHkgKyBxeiAqIHggLSBxeCAqIHosXG4gICAgICAgIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4LFxuICAgICAgICBpdyA9IC1xeCAqIHggLSBxeSAqIHkgLSBxeiAqIHo7XG5cbiAgICAvLyBjYWxjdWxhdGUgcmVzdWx0ICogaW52ZXJzZSBxdWF0XG4gICAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeTtcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6O1xuICAgIG91dFsyXSA9IGl6ICogcXcgKyBpdyAqIC1xeiArIGl4ICogLXF5IC0gaXkgKiAtcXg7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHgtYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVggPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICAgdmFyIHAgPSBbXSwgcj1bXTtcblx0ICAvL1RyYW5zbGF0ZSBwb2ludCB0byB0aGUgb3JpZ2luXG5cdCAgcFswXSA9IGFbMF0gLSBiWzBdO1xuXHQgIHBbMV0gPSBhWzFdIC0gYlsxXTtcbiAgXHRwWzJdID0gYVsyXSAtIGJbMl07XG5cblx0ICAvL3BlcmZvcm0gcm90YXRpb25cblx0ICByWzBdID0gcFswXTtcblx0ICByWzFdID0gcFsxXSpNYXRoLmNvcyhjKSAtIHBbMl0qTWF0aC5zaW4oYyk7XG5cdCAgclsyXSA9IHBbMV0qTWF0aC5zaW4oYykgKyBwWzJdKk1hdGguY29zKGMpO1xuXG5cdCAgLy90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuXHQgIG91dFswXSA9IHJbMF0gKyBiWzBdO1xuXHQgIG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuXHQgIG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuXG4gIFx0cmV0dXJuIG91dDtcbn07XG5cbi8qXG4qIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHktYXhpc1xuKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uXG4qIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiovXG52ZWMzLnJvdGF0ZVkgPSBmdW5jdGlvbihvdXQsIGEsIGIsIGMpe1xuICBcdHZhciBwID0gW10sIHI9W107XG4gIFx0Ly9UcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICBcdHBbMF0gPSBhWzBdIC0gYlswXTtcbiAgXHRwWzFdID0gYVsxXSAtIGJbMV07XG4gIFx0cFsyXSA9IGFbMl0gLSBiWzJdO1xuICBcbiAgXHQvL3BlcmZvcm0gcm90YXRpb25cbiAgXHRyWzBdID0gcFsyXSpNYXRoLnNpbihjKSArIHBbMF0qTWF0aC5jb3MoYyk7XG4gIFx0clsxXSA9IHBbMV07XG4gIFx0clsyXSA9IHBbMl0qTWF0aC5jb3MoYykgLSBwWzBdKk1hdGguc2luKGMpO1xuICBcbiAgXHQvL3RyYW5zbGF0ZSB0byBjb3JyZWN0IHBvc2l0aW9uXG4gIFx0b3V0WzBdID0gclswXSArIGJbMF07XG4gIFx0b3V0WzFdID0gclsxXSArIGJbMV07XG4gIFx0b3V0WzJdID0gclsyXSArIGJbMl07XG4gIFxuICBcdHJldHVybiBvdXQ7XG59O1xuXG4vKlxuKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB6LWF4aXNcbiogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4qIEBwYXJhbSB7dmVjM30gYSBUaGUgdmVjMyBwb2ludCB0byByb3RhdGVcbiogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4qIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuKiBAcmV0dXJucyB7dmVjM30gb3V0XG4qL1xudmVjMy5yb3RhdGVaID0gZnVuY3Rpb24ob3V0LCBhLCBiLCBjKXtcbiAgXHR2YXIgcCA9IFtdLCByPVtdO1xuICBcdC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgXHRwWzBdID0gYVswXSAtIGJbMF07XG4gIFx0cFsxXSA9IGFbMV0gLSBiWzFdO1xuICBcdHBbMl0gPSBhWzJdIC0gYlsyXTtcbiAgXG4gIFx0Ly9wZXJmb3JtIHJvdGF0aW9uXG4gIFx0clswXSA9IHBbMF0qTWF0aC5jb3MoYykgLSBwWzFdKk1hdGguc2luKGMpO1xuICBcdHJbMV0gPSBwWzBdKk1hdGguc2luKGMpICsgcFsxXSpNYXRoLmNvcyhjKTtcbiAgXHRyWzJdID0gcFsyXTtcbiAgXG4gIFx0Ly90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuICBcdG91dFswXSA9IHJbMF0gKyBiWzBdO1xuICBcdG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuICBcdG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuICBcbiAgXHRyZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjM3MuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjMy4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzNzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG52ZWMzLmZvckVhY2ggPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZlYyA9IHZlYzMuY3JlYXRlKCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBpZighc3RyaWRlKSB7XG4gICAgICAgICAgICBzdHJpZGUgPSAzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYoY291bnQpIHtcbiAgICAgICAgICAgIGwgPSBNYXRoLm1pbigoY291bnQgKiBzdHJpZGUpICsgb2Zmc2V0LCBhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsID0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldOyB2ZWNbMV0gPSBhW2krMV07IHZlY1syXSA9IGFbaSsyXTtcbiAgICAgICAgICAgIGZuKHZlYywgdmVjLCBhcmcpO1xuICAgICAgICAgICAgYVtpXSA9IHZlY1swXTsgYVtpKzFdID0gdmVjWzFdOyBhW2krMl0gPSB2ZWNbMl07XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWMzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWMzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcpJztcbn07XG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLnZlYzMgPSB2ZWMzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNCBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBuYW1lIHZlYzRcbiAqL1xuXG52YXIgdmVjNCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbnZlYzQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWM0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG52ZWM0LmZyb21WYWx1ZXMgPSBmdW5jdGlvbih4LCB5LCB6LCB3KSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IHg7XG4gICAgb3V0WzFdID0geTtcbiAgICBvdXRbMl0gPSB6O1xuICAgIG91dFszXSA9IHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHZlYzQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zZXQgPSBmdW5jdGlvbihvdXQsIHgsIHksIHosIHcpIHtcbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSB3O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5hZGQgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgICBvdXRbM10gPSBhWzNdICsgYlszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTdWJ0cmFjdHMgdmVjdG9yIGIgZnJvbSB2ZWN0b3IgYVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zdWJ0cmFjdCA9IGZ1bmN0aW9uKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdO1xuICAgIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICAgIG91dFszXSA9IGFbM10gLSBiWzNdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LnN1YiA9IHZlYzQuc3VidHJhY3Q7XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0Lm11bHRpcGx5ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAqIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAqIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubXVsID0gdmVjNC5tdWx0aXBseTtcblxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuZGl2aWRlID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV07XG4gICAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gICAgb3V0WzNdID0gYVszXSAvIGJbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LmRpdmlkZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpdiA9IHZlYzQuZGl2aWRlO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5taW4gPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgICBvdXRbM10gPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtYXhpbXVtIG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubWF4ID0gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gICAgb3V0WzFdID0gTWF0aC5tYXgoYVsxXSwgYlsxXSk7XG4gICAgb3V0WzJdID0gTWF0aC5tYXgoYVsyXSwgYlsyXSk7XG4gICAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICogYjtcbiAgICBvdXRbMV0gPSBhWzFdICogYjtcbiAgICBvdXRbMl0gPSBhWzJdICogYjtcbiAgICBvdXRbM10gPSBhWzNdICogYjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5zY2FsZUFuZEFkZCA9IGZ1bmN0aW9uKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgKGJbMF0gKiBzY2FsZSk7XG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpO1xuICAgIG91dFsyXSA9IGFbMl0gKyAoYlsyXSAqIHNjYWxlKTtcbiAgICBvdXRbM10gPSBhWzNdICsgKGJbM10gKiBzY2FsZSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbnZlYzQuZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeiArIHcqdyk7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG52ZWM0LmRpc3QgPSB2ZWM0LmRpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xudmVjNC5zcXVhcmVkRGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgICAgIHcgPSBiWzNdIC0gYVszXTtcbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6ICsgdyp3O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3F1YXJlZERpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuc3FyRGlzdCA9IHZlYzQuc3F1YXJlZERpc3RhbmNlO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbnZlYzQubGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIE1hdGguc3FydCh4KnggKyB5KnkgKyB6KnogKyB3KncpO1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQubGVuID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xudmVjNC5zcXVhcmVkTGVuZ3RoID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgeCA9IGFbMF0sXG4gICAgICAgIHkgPSBhWzFdLFxuICAgICAgICB6ID0gYVsyXSxcbiAgICAgICAgdyA9IGFbM107XG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqeiArIHcqdztcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWM0LnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xudmVjNC5zcXJMZW4gPSB2ZWM0LnNxdWFyZWRMZW5ndGg7XG5cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xudmVjNC5uZWdhdGUgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSAtYVswXTtcbiAgICBvdXRbMV0gPSAtYVsxXTtcbiAgICBvdXRbMl0gPSAtYVsyXTtcbiAgICBvdXRbM10gPSAtYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQubm9ybWFsaXplID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl0sXG4gICAgICAgIHcgPSBhWzNdO1xuICAgIHZhciBsZW4gPSB4KnggKyB5KnkgKyB6KnogKyB3Knc7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pO1xuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuO1xuICAgICAgICBvdXRbMV0gPSBhWzFdICogbGVuO1xuICAgICAgICBvdXRbMl0gPSBhWzJdICogbGVuO1xuICAgICAgICBvdXRbM10gPSBhWzNdICogbGVuO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbnZlYzQuZG90ID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM107XG59O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LmxlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl0sXG4gICAgICAgIGF3ID0gYVszXTtcbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgICBvdXRbMl0gPSBheiArIHQgKiAoYlsyXSAtIGF6KTtcbiAgICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnJhbmRvbSA9IGZ1bmN0aW9uIChvdXQsIHNjYWxlKSB7XG4gICAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7XG5cbiAgICAvL1RPRE86IFRoaXMgaXMgYSBwcmV0dHkgYXdmdWwgd2F5IG9mIGRvaW5nIHRoaXMuIEZpbmQgc29tZXRoaW5nIGJldHRlci5cbiAgICBvdXRbMF0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMV0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbMl0gPSBHTE1BVF9SQU5ET00oKTtcbiAgICBvdXRbM10gPSBHTE1BVF9SQU5ET00oKTtcbiAgICB2ZWM0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgdmVjNC5zY2FsZShvdXQsIG91dCwgc2NhbGUpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzQgd2l0aCBhIG1hdDQuXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIG1hdHJpeCB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG52ZWM0LnRyYW5zZm9ybU1hdDQgPSBmdW5jdGlvbihvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM107XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogdztcbiAgICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3O1xuICAgIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7cXVhdH0gcSBxdWF0ZXJuaW9uIHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbnZlYzQudHJhbnNmb3JtUXVhdCA9IGZ1bmN0aW9uKG91dCwgYSwgcSkge1xuICAgIHZhciB4ID0gYVswXSwgeSA9IGFbMV0sIHogPSBhWzJdLFxuICAgICAgICBxeCA9IHFbMF0sIHF5ID0gcVsxXSwgcXogPSBxWzJdLCBxdyA9IHFbM10sXG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHF1YXQgKiB2ZWNcbiAgICAgICAgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHksXG4gICAgICAgIGl5ID0gcXcgKiB5ICsgcXogKiB4IC0gcXggKiB6LFxuICAgICAgICBpeiA9IHF3ICogeiArIHF4ICogeSAtIHF5ICogeCxcbiAgICAgICAgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6O1xuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXk7XG4gICAgb3V0WzFdID0gaXkgKiBxdyArIGl3ICogLXF5ICsgaXogKiAtcXggLSBpeCAqIC1xejtcbiAgICBvdXRbMl0gPSBpeiAqIHF3ICsgaXcgKiAtcXogKyBpeCAqIC1xeSAtIGl5ICogLXF4O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFBlcmZvcm0gc29tZSBvcGVyYXRpb24gb3ZlciBhbiBhcnJheSBvZiB2ZWM0cy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhIHRoZSBhcnJheSBvZiB2ZWN0b3JzIHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIHtOdW1iZXJ9IHN0cmlkZSBOdW1iZXIgb2YgZWxlbWVudHMgYmV0d2VlbiB0aGUgc3RhcnQgb2YgZWFjaCB2ZWM0LiBJZiAwIGFzc3VtZXMgdGlnaHRseSBwYWNrZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXQgTnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNraXAgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudCBOdW1iZXIgb2YgdmVjMnMgdG8gaXRlcmF0ZSBvdmVyLiBJZiAwIGl0ZXJhdGVzIG92ZXIgZW50aXJlIGFycmF5XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbYXJnXSBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHBhc3MgdG8gZm5cbiAqIEByZXR1cm5zIHtBcnJheX0gYVxuICogQGZ1bmN0aW9uXG4gKi9cbnZlYzQuZm9yRWFjaCA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdmVjID0gdmVjNC5jcmVhdGUoKTtcblxuICAgIHJldHVybiBmdW5jdGlvbihhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGlmKCFzdHJpZGUpIHtcbiAgICAgICAgICAgIHN0cmlkZSA9IDQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZighb2Zmc2V0KSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGwgPSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gb2Zmc2V0OyBpIDwgbDsgaSArPSBzdHJpZGUpIHtcbiAgICAgICAgICAgIHZlY1swXSA9IGFbaV07IHZlY1sxXSA9IGFbaSsxXTsgdmVjWzJdID0gYVtpKzJdOyB2ZWNbM10gPSBhW2krM107XG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKTtcbiAgICAgICAgICAgIGFbaV0gPSB2ZWNbMF07IGFbaSsxXSA9IHZlY1sxXTsgYVtpKzJdID0gdmVjWzJdOyBhW2krM10gPSB2ZWNbM107XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG52ZWM0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICd2ZWM0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMudmVjNCA9IHZlYzQ7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDIgTWF0cml4XG4gKiBAbmFtZSBtYXQyXG4gKi9cblxudmFyIG1hdDIgPSB7fTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGlkZW50aXR5IG1hdDJcbiAqXG4gKiBAcmV0dXJucyB7bWF0Mn0gYSBuZXcgMngyIG1hdHJpeFxuICovXG5tYXQyLmNyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg0KTtcbiAgICBvdXRbMF0gPSAxO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MiBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSBtYXRyaXggdG8gY2xvbmVcbiAqIEByZXR1cm5zIHttYXQyfSBhIG5ldyAyeDIgbWF0cml4XG4gKi9cbm1hdDIuY2xvbmUgPSBmdW5jdGlvbihhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDIgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqL1xubWF0Mi5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQyIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGExID0gYVsxXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVsyXTtcbiAgICAgICAgb3V0WzJdID0gYVsxXTtcbiAgICAgICAgb3V0WzNdID0gYVszXTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGEwICogYTMgLSBhMiAqIGExO1xuXG4gICAgaWYgKCFkZXQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcbiAgICBcbiAgICBvdXRbMF0gPSAgYTMgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWExICogZGV0O1xuICAgIG91dFsyXSA9IC1hMiAqIGRldDtcbiAgICBvdXRbM10gPSAgYTAgKiBkZXQ7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhZGp1Z2F0ZSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIuYWRqb2ludCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIENhY2hpbmcgdGhpcyB2YWx1ZSBpcyBuZXNzZWNhcnkgaWYgb3V0ID09IGFcbiAgICB2YXIgYTAgPSBhWzBdO1xuICAgIG91dFswXSA9ICBhWzNdO1xuICAgIG91dFsxXSA9IC1hWzFdO1xuICAgIG91dFsyXSA9IC1hWzJdO1xuICAgIG91dFszXSA9ICBhMDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MlxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQyLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzJdICogYVsxXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MidzXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDJ9IG91dFxuICovXG5tYXQyLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM107XG4gICAgdmFyIGIwID0gYlswXSwgYjEgPSBiWzFdLCBiMiA9IGJbMl0sIGIzID0gYlszXTtcbiAgICBvdXRbMF0gPSBhMCAqIGIwICsgYTIgKiBiMTtcbiAgICBvdXRbMV0gPSBhMSAqIGIwICsgYTMgKiBiMTtcbiAgICBvdXRbMl0gPSBhMCAqIGIyICsgYTIgKiBiMztcbiAgICBvdXRbM10gPSBhMSAqIGIyICsgYTMgKiBiMztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDIubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0Mi5tdWwgPSBtYXQyLm11bHRpcGx5O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQyIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0Mn0gb3V0XG4gKi9cbm1hdDIucm90YXRlID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICAgIG91dFswXSA9IGEwICogIGMgKyBhMiAqIHM7XG4gICAgb3V0WzFdID0gYTEgKiAgYyArIGEzICogcztcbiAgICBvdXRbMl0gPSBhMCAqIC1zICsgYTIgKiBjO1xuICAgIG91dFszXSA9IGExICogLXMgKyBhMyAqIGM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQyIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMyfSB2IHRoZSB2ZWMyIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqKi9cbm1hdDIuc2NhbGUgPSBmdW5jdGlvbihvdXQsIGEsIHYpIHtcbiAgICB2YXIgYTAgPSBhWzBdLCBhMSA9IGFbMV0sIGEyID0gYVsyXSwgYTMgPSBhWzNdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMCAqIHYwO1xuICAgIG91dFsxXSA9IGExICogdjA7XG4gICAgb3V0WzJdID0gYTIgKiB2MTtcbiAgICBvdXRbM10gPSBhMyAqIHYxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQyXG4gKlxuICogQHBhcmFtIHttYXQyfSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0Mi5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MignICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJcbiAqXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIG1hdHJpeCB0byBjYWxjdWxhdGUgRnJvYmVuaXVzIG5vcm0gb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IEZyb2Jlbml1cyBub3JtXG4gKi9cbm1hdDIuZnJvYiA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuKE1hdGguc3FydChNYXRoLnBvdyhhWzBdLCAyKSArIE1hdGgucG93KGFbMV0sIDIpICsgTWF0aC5wb3coYVsyXSwgMikgKyBNYXRoLnBvdyhhWzNdLCAyKSkpXG59O1xuXG4vKipcbiAqIFJldHVybnMgTCwgRCBhbmQgVSBtYXRyaWNlcyAoTG93ZXIgdHJpYW5ndWxhciwgRGlhZ29uYWwgYW5kIFVwcGVyIHRyaWFuZ3VsYXIpIGJ5IGZhY3Rvcml6aW5nIHRoZSBpbnB1dCBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0Mn0gTCB0aGUgbG93ZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IEQgdGhlIGRpYWdvbmFsIG1hdHJpeCBcbiAqIEBwYXJhbSB7bWF0Mn0gVSB0aGUgdXBwZXIgdHJpYW5ndWxhciBtYXRyaXggXG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIGlucHV0IG1hdHJpeCB0byBmYWN0b3JpemVcbiAqL1xuXG5tYXQyLkxEVSA9IGZ1bmN0aW9uIChMLCBELCBVLCBhKSB7IFxuICAgIExbMl0gPSBhWzJdL2FbMF07IFxuICAgIFVbMF0gPSBhWzBdOyBcbiAgICBVWzFdID0gYVsxXTsgXG4gICAgVVszXSA9IGFbM10gLSBMWzJdICogVVsxXTsgXG4gICAgcmV0dXJuIFtMLCBELCBVXTsgICAgICAgXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MiA9IG1hdDI7XG59XG47XG4vKiBDb3B5cmlnaHQgKGMpIDIwMTMsIEJyYW5kb24gSm9uZXMsIENvbGluIE1hY0tlbnppZSBJVi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIFxuICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG5XQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIFxuRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcbkFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xuTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXG5BTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcblNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLiAqL1xuXG4vKipcbiAqIEBjbGFzcyAyeDMgTWF0cml4XG4gKiBAbmFtZSBtYXQyZFxuICogXG4gKiBAZGVzY3JpcHRpb24gXG4gKiBBIG1hdDJkIGNvbnRhaW5zIHNpeCBlbGVtZW50cyBkZWZpbmVkIGFzOlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eV1cbiAqIDwvcHJlPlxuICogVGhpcyBpcyBhIHNob3J0IGZvcm0gZm9yIHRoZSAzeDMgbWF0cml4OlxuICogPHByZT5cbiAqIFthLCBjLCB0eCxcbiAqICBiLCBkLCB0eSxcbiAqICAwLCAwLCAxXVxuICogPC9wcmU+XG4gKiBUaGUgbGFzdCByb3cgaXMgaWdub3JlZCBzbyB0aGUgYXJyYXkgaXMgc2hvcnRlciBhbmQgb3BlcmF0aW9ucyBhcmUgZmFzdGVyLlxuICovXG5cbnZhciBtYXQyZCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0MmRcbiAqXG4gKiBAcmV0dXJucyB7bWF0MmR9IGEgbmV3IDJ4MyBtYXRyaXhcbiAqL1xubWF0MmQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0MmQgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDJkfSBhIG5ldyAyeDMgbWF0cml4XG4gKi9cbm1hdDJkLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg2KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MmQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqL1xubWF0MmQuY29weSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldCBhIG1hdDJkIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMTtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDA7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0MmR9IG91dFxuICovXG5tYXQyZC5pbnZlcnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYWEgPSBhWzBdLCBhYiA9IGFbMV0sIGFjID0gYVsyXSwgYWQgPSBhWzNdLFxuICAgICAgICBhdHggPSBhWzRdLCBhdHkgPSBhWzVdO1xuXG4gICAgdmFyIGRldCA9IGFhICogYWQgLSBhYiAqIGFjO1xuICAgIGlmKCFkZXQpe1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYWQgKiBkZXQ7XG4gICAgb3V0WzFdID0gLWFiICogZGV0O1xuICAgIG91dFsyXSA9IC1hYyAqIGRldDtcbiAgICBvdXRbM10gPSBhYSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYWMgKiBhdHkgLSBhZCAqIGF0eCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKGFiICogYXR4IC0gYWEgKiBhdHkpICogZGV0O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0MmRcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDJkLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4gYVswXSAqIGFbM10gLSBhWzFdICogYVsyXTtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0MmQnc1xuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQyZH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBiMCA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM10sIGI0ID0gYls0XSwgYjUgPSBiWzVdO1xuICAgIG91dFswXSA9IGEwICogYjAgKyBhMiAqIGIxO1xuICAgIG91dFsxXSA9IGExICogYjAgKyBhMyAqIGIxO1xuICAgIG91dFsyXSA9IGEwICogYjIgKyBhMiAqIGIzO1xuICAgIG91dFszXSA9IGExICogYjIgKyBhMyAqIGIzO1xuICAgIG91dFs0XSA9IGEwICogYjQgKyBhMiAqIGI1ICsgYTQ7XG4gICAgb3V0WzVdID0gYTEgKiBiNCArIGEzICogYjUgKyBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDJkLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDJkLm11bCA9IG1hdDJkLm11bHRpcGx5O1xuXG5cbi8qKlxuICogUm90YXRlcyBhIG1hdDJkIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0MmR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQyZH0gb3V0XG4gKi9cbm1hdDJkLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgb3V0WzBdID0gYTAgKiAgYyArIGEyICogcztcbiAgICBvdXRbMV0gPSBhMSAqICBjICsgYTMgKiBzO1xuICAgIG91dFsyXSA9IGEwICogLXMgKyBhMiAqIGM7XG4gICAgb3V0WzNdID0gYTEgKiAtcyArIGEzICogYztcbiAgICBvdXRbNF0gPSBhNDtcbiAgICBvdXRbNV0gPSBhNTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDJkIGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMyXG4gKlxuICogQHBhcmFtIHttYXQyZH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJkfSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnNjYWxlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSwgYTQgPSBhWzRdLCBhNSA9IGFbNV0sXG4gICAgICAgIHYwID0gdlswXSwgdjEgPSB2WzFdO1xuICAgIG91dFswXSA9IGEwICogdjA7XG4gICAgb3V0WzFdID0gYTEgKiB2MDtcbiAgICBvdXRbMl0gPSBhMiAqIHYxO1xuICAgIG91dFszXSA9IGEzICogdjE7XG4gICAgb3V0WzRdID0gYTQ7XG4gICAgb3V0WzVdID0gYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNsYXRlcyB0aGUgbWF0MmQgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDJkfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB0aGUgdmVjMiB0byB0cmFuc2xhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDJkfSBvdXRcbiAqKi9cbm1hdDJkLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciBhMCA9IGFbMF0sIGExID0gYVsxXSwgYTIgPSBhWzJdLCBhMyA9IGFbM10sIGE0ID0gYVs0XSwgYTUgPSBhWzVdLFxuICAgICAgICB2MCA9IHZbMF0sIHYxID0gdlsxXTtcbiAgICBvdXRbMF0gPSBhMDtcbiAgICBvdXRbMV0gPSBhMTtcbiAgICBvdXRbMl0gPSBhMjtcbiAgICBvdXRbM10gPSBhMztcbiAgICBvdXRbNF0gPSBhMCAqIHYwICsgYTIgKiB2MSArIGE0O1xuICAgIG91dFs1XSA9IGExICogdjAgKyBhMyAqIHYxICsgYTU7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQyZC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0MmQoJyArIGFbMF0gKyAnLCAnICsgYVsxXSArICcsICcgKyBhWzJdICsgJywgJyArIFxuICAgICAgICAgICAgICAgICAgICBhWzNdICsgJywgJyArIGFbNF0gKyAnLCAnICsgYVs1XSArICcpJztcbn07XG5cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDJkXG4gKlxuICogQHBhcmFtIHttYXQyZH0gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0MmQuZnJvYiA9IGZ1bmN0aW9uIChhKSB7IFxuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgMSkpXG59OyBcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMubWF0MmQgPSBtYXQyZDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIDN4MyBNYXRyaXhcbiAqIEBuYW1lIG1hdDNcbiAqL1xuXG52YXIgbWF0MyA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0M1xuICpcbiAqIEByZXR1cm5zIHttYXQzfSBhIG5ldyAzeDMgbWF0cml4XG4gKi9cbm1hdDMuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDkpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMTtcbiAgICBvdXRbNV0gPSAwO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENvcGllcyB0aGUgdXBwZXItbGVmdCAzeDMgdmFsdWVzIGludG8gdGhlIGdpdmVuIG1hdDMuXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyAzeDMgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgICB0aGUgc291cmNlIDR4NCBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xubWF0My5mcm9tTWF0NCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbNF07XG4gICAgb3V0WzRdID0gYVs1XTtcbiAgICBvdXRbNV0gPSBhWzZdO1xuICAgIG91dFs2XSA9IGFbOF07XG4gICAgb3V0WzddID0gYVs5XTtcbiAgICBvdXRbOF0gPSBhWzEwXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IG1hdDMgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IGEgbWF0cml4IHRvIGNsb25lXG4gKiBAcmV0dXJucyB7bWF0M30gYSBuZXcgM3gzIG1hdHJpeFxuICovXG5tYXQzLmNsb25lID0gZnVuY3Rpb24oYSkge1xuICAgIHZhciBvdXQgPSBuZXcgR0xNQVRfQVJSQVlfVFlQRSg5KTtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0MyB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmNvcHkgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbMV07XG4gICAgb3V0WzJdID0gYVsyXTtcbiAgICBvdXRbM10gPSBhWzNdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQzIHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAxO1xuICAgIG91dFs1XSA9IDA7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHJhbnNwb3NlIHRoZSB2YWx1ZXMgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnRyYW5zcG9zZSA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgICBpZiAob3V0ID09PSBhKSB7XG4gICAgICAgIHZhciBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMTIgPSBhWzVdO1xuICAgICAgICBvdXRbMV0gPSBhWzNdO1xuICAgICAgICBvdXRbMl0gPSBhWzZdO1xuICAgICAgICBvdXRbM10gPSBhMDE7XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGEwMjtcbiAgICAgICAgb3V0WzddID0gYTEyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFswXSA9IGFbMF07XG4gICAgICAgIG91dFsxXSA9IGFbM107XG4gICAgICAgIG91dFsyXSA9IGFbNl07XG4gICAgICAgIG91dFszXSA9IGFbMV07XG4gICAgICAgIG91dFs0XSA9IGFbNF07XG4gICAgICAgIG91dFs1XSA9IGFbN107XG4gICAgICAgIG91dFs2XSA9IGFbMl07XG4gICAgICAgIG91dFs3XSA9IGFbNV07XG4gICAgICAgIG91dFs4XSA9IGFbOF07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmludmVydCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIGIwMSA9IGEyMiAqIGExMSAtIGExMiAqIGEyMSxcbiAgICAgICAgYjExID0gLWEyMiAqIGExMCArIGExMiAqIGEyMCxcbiAgICAgICAgYjIxID0gYTIxICogYTEwIC0gYTExICogYTIwLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gYjAxICogZGV0O1xuICAgIG91dFsxXSA9ICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldDtcbiAgICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldDtcbiAgICBvdXRbM10gPSBiMTEgKiBkZXQ7XG4gICAgb3V0WzRdID0gKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0O1xuICAgIG91dFs2XSA9IGIyMSAqIGRldDtcbiAgICBvdXRbN10gPSAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXQ7XG4gICAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQ7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIG91dFswXSA9IChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpO1xuICAgIG91dFsxXSA9IChhMDIgKiBhMjEgLSBhMDEgKiBhMjIpO1xuICAgIG91dFsyXSA9IChhMDEgKiBhMTIgLSBhMDIgKiBhMTEpO1xuICAgIG91dFszXSA9IChhMTIgKiBhMjAgLSBhMTAgKiBhMjIpO1xuICAgIG91dFs0XSA9IChhMDAgKiBhMjIgLSBhMDIgKiBhMjApO1xuICAgIG91dFs1XSA9IChhMDIgKiBhMTAgLSBhMDAgKiBhMTIpO1xuICAgIG91dFs2XSA9IChhMTAgKiBhMjEgLSBhMTEgKiBhMjApO1xuICAgIG91dFs3XSA9IChhMDEgKiBhMjAgLSBhMDAgKiBhMjEpO1xuICAgIG91dFs4XSA9IChhMDAgKiBhMTEgLSBhMDEgKiBhMTApO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRldGVybWluYW50IG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5tYXQzLmRldGVybWluYW50ID0gZnVuY3Rpb24gKGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSxcbiAgICAgICAgYTEwID0gYVszXSwgYTExID0gYVs0XSwgYTEyID0gYVs1XSxcbiAgICAgICAgYTIwID0gYVs2XSwgYTIxID0gYVs3XSwgYTIyID0gYVs4XTtcblxuICAgIHJldHVybiBhMDAgKiAoYTIyICogYTExIC0gYTEyICogYTIxKSArIGEwMSAqICgtYTIyICogYTEwICsgYTEyICogYTIwKSArIGEwMiAqIChhMjEgKiBhMTAgLSBhMTEgKiBhMjApO1xufTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQzJ3NcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge21hdDN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMubXVsdGlwbHkgPSBmdW5jdGlvbiAob3V0LCBhLCBiKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG5cbiAgICAgICAgYjAwID0gYlswXSwgYjAxID0gYlsxXSwgYjAyID0gYlsyXSxcbiAgICAgICAgYjEwID0gYlszXSwgYjExID0gYls0XSwgYjEyID0gYls1XSxcbiAgICAgICAgYjIwID0gYls2XSwgYjIxID0gYls3XSwgYjIyID0gYls4XTtcblxuICAgIG91dFswXSA9IGIwMCAqIGEwMCArIGIwMSAqIGExMCArIGIwMiAqIGEyMDtcbiAgICBvdXRbMV0gPSBiMDAgKiBhMDEgKyBiMDEgKiBhMTEgKyBiMDIgKiBhMjE7XG4gICAgb3V0WzJdID0gYjAwICogYTAyICsgYjAxICogYTEyICsgYjAyICogYTIyO1xuXG4gICAgb3V0WzNdID0gYjEwICogYTAwICsgYjExICogYTEwICsgYjEyICogYTIwO1xuICAgIG91dFs0XSA9IGIxMCAqIGEwMSArIGIxMSAqIGExMSArIGIxMiAqIGEyMTtcbiAgICBvdXRbNV0gPSBiMTAgKiBhMDIgKyBiMTEgKiBhMTIgKyBiMTIgKiBhMjI7XG5cbiAgICBvdXRbNl0gPSBiMjAgKiBhMDAgKyBiMjEgKiBhMTAgKyBiMjIgKiBhMjA7XG4gICAgb3V0WzddID0gYjIwICogYTAxICsgYjIxICogYTExICsgYjIyICogYTIxO1xuICAgIG91dFs4XSA9IGIyMCAqIGEwMiArIGIyMSAqIGExMiArIGIyMiAqIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDMubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xubWF0My5tdWwgPSBtYXQzLm11bHRpcGx5O1xuXG4vKipcbiAqIFRyYW5zbGF0ZSBhIG1hdDMgYnkgdGhlIGdpdmVuIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDN9IGEgdGhlIG1hdHJpeCB0byB0cmFuc2xhdGVcbiAqIEBwYXJhbSB7dmVjMn0gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbm1hdDMudHJhbnNsYXRlID0gZnVuY3Rpb24ob3V0LCBhLCB2KSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sXG4gICAgICAgIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV0sXG4gICAgICAgIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF0sXG4gICAgICAgIHggPSB2WzBdLCB5ID0gdlsxXTtcblxuICAgIG91dFswXSA9IGEwMDtcbiAgICBvdXRbMV0gPSBhMDE7XG4gICAgb3V0WzJdID0gYTAyO1xuXG4gICAgb3V0WzNdID0gYTEwO1xuICAgIG91dFs0XSA9IGExMTtcbiAgICBvdXRbNV0gPSBhMTI7XG5cbiAgICBvdXRbNl0gPSB4ICogYTAwICsgeSAqIGExMCArIGEyMDtcbiAgICBvdXRbN10gPSB4ICogYTAxICsgeSAqIGExMSArIGEyMTtcbiAgICBvdXRbOF0gPSB4ICogYTAyICsgeSAqIGExMiArIGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0MyBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5tYXQzLnJvdGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLFxuICAgICAgICBhMTAgPSBhWzNdLCBhMTEgPSBhWzRdLCBhMTIgPSBhWzVdLFxuICAgICAgICBhMjAgPSBhWzZdLCBhMjEgPSBhWzddLCBhMjIgPSBhWzhdLFxuXG4gICAgICAgIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKTtcblxuICAgIG91dFswXSA9IGMgKiBhMDAgKyBzICogYTEwO1xuICAgIG91dFsxXSA9IGMgKiBhMDEgKyBzICogYTExO1xuICAgIG91dFsyXSA9IGMgKiBhMDIgKyBzICogYTEyO1xuXG4gICAgb3V0WzNdID0gYyAqIGExMCAtIHMgKiBhMDA7XG4gICAgb3V0WzRdID0gYyAqIGExMSAtIHMgKiBhMDE7XG4gICAgb3V0WzVdID0gYyAqIGExMiAtIHMgKiBhMDI7XG5cbiAgICBvdXRbNl0gPSBhMjA7XG4gICAgb3V0WzddID0gYTIxO1xuICAgIG91dFs4XSA9IGEyMjtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDMgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzJ9IHYgdGhlIHZlYzIgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICoqL1xubWF0My5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV07XG5cbiAgICBvdXRbMF0gPSB4ICogYVswXTtcbiAgICBvdXRbMV0gPSB4ICogYVsxXTtcbiAgICBvdXRbMl0gPSB4ICogYVsyXTtcblxuICAgIG91dFszXSA9IHkgKiBhWzNdO1xuICAgIG91dFs0XSA9IHkgKiBhWzRdO1xuICAgIG91dFs1XSA9IHkgKiBhWzVdO1xuXG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29waWVzIHRoZSB2YWx1ZXMgZnJvbSBhIG1hdDJkIGludG8gYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0MmR9IGEgdGhlIG1hdHJpeCB0byBjb3B5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKiovXG5tYXQzLmZyb21NYXQyZCA9IGZ1bmN0aW9uKG91dCwgYSkge1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSAwO1xuXG4gICAgb3V0WzNdID0gYVsyXTtcbiAgICBvdXRbNF0gPSBhWzNdO1xuICAgIG91dFs1XSA9IDA7XG5cbiAgICBvdXRbNl0gPSBhWzRdO1xuICAgIG91dFs3XSA9IGFbNV07XG4gICAgb3V0WzhdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbWF0cml4IGZyb20gdGhlIGdpdmVuIHF1YXRlcm5pb25cbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge3F1YXR9IHEgUXVhdGVybmlvbiB0byBjcmVhdGUgbWF0cml4IGZyb21cbipcbiogQHJldHVybnMge21hdDN9IG91dFxuKi9cbm1hdDMuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbM10gPSB5eCAtIHd6O1xuICAgIG91dFs2XSA9IHp4ICsgd3k7XG5cbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFs0XSA9IDEgLSB4eCAtIHp6O1xuICAgIG91dFs3XSA9IHp5IC0gd3g7XG5cbiAgICBvdXRbMl0gPSB6eCAtIHd5O1xuICAgIG91dFs1XSA9IHp5ICsgd3g7XG4gICAgb3V0WzhdID0gMSAtIHh4IC0geXk7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4qIENhbGN1bGF0ZXMgYSAzeDMgbm9ybWFsIG1hdHJpeCAodHJhbnNwb3NlIGludmVyc2UpIGZyb20gdGhlIDR4NCBtYXRyaXhcbipcbiogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuKiBAcGFyYW0ge21hdDR9IGEgTWF0NCB0byBkZXJpdmUgdGhlIG5vcm1hbCBtYXRyaXggZnJvbVxuKlxuKiBAcmV0dXJucyB7bWF0M30gb3V0XG4qL1xubWF0My5ub3JtYWxGcm9tTWF0NCA9IGZ1bmN0aW9uIChvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XSxcblxuICAgICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXG4gICAgICAgIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMCxcbiAgICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxuICAgICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXG4gICAgICAgIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMSxcbiAgICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxuICAgICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXG4gICAgICAgIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMCxcbiAgICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxuICAgICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXG4gICAgICAgIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMSxcbiAgICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzFdID0gKGExMiAqIGIwOCAtIGExMCAqIGIxMSAtIGExMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzJdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG5cbiAgICBvdXRbM10gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgICBvdXRbNF0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgICBvdXRbNV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcblxuICAgIG91dFs2XSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFs3XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG1hdCBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5tYXQzLnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdtYXQzKCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVszXSArICcsICcgKyBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgXG4gICAgICAgICAgICAgICAgICAgIGFbNl0gKyAnLCAnICsgYVs3XSArICcsICcgKyBhWzhdICsgJyknO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIEZyb2Jlbml1cyBub3JtIG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xubWF0My5mcm9iID0gZnVuY3Rpb24gKGEpIHtcbiAgICByZXR1cm4oTWF0aC5zcXJ0KE1hdGgucG93KGFbMF0sIDIpICsgTWF0aC5wb3coYVsxXSwgMikgKyBNYXRoLnBvdyhhWzJdLCAyKSArIE1hdGgucG93KGFbM10sIDIpICsgTWF0aC5wb3coYVs0XSwgMikgKyBNYXRoLnBvdyhhWzVdLCAyKSArIE1hdGgucG93KGFbNl0sIDIpICsgTWF0aC5wb3coYVs3XSwgMikgKyBNYXRoLnBvdyhhWzhdLCAyKSkpXG59O1xuXG5cbmlmKHR5cGVvZihleHBvcnRzKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBleHBvcnRzLm1hdDMgPSBtYXQzO1xufVxuO1xuLyogQ29weXJpZ2h0IChjKSAyMDEzLCBCcmFuZG9uIEpvbmVzLCBDb2xpbiBNYWNLZW56aWUgSVYuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cblJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG5hcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBcbiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG5BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBcbkRJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXG5BTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbihJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxuQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbihJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG5TT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4gKi9cblxuLyoqXG4gKiBAY2xhc3MgNHg0IE1hdHJpeFxuICogQG5hbWUgbWF0NFxuICovXG5cbnZhciBtYXQ0ID0ge307XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBpZGVudGl0eSBtYXQ0XG4gKlxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQ0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xubWF0NC5jbG9uZSA9IGZ1bmN0aW9uKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEdMTUFUX0FSUkFZX1RZUEUoMTYpO1xuICAgIG91dFswXSA9IGFbMF07XG4gICAgb3V0WzFdID0gYVsxXTtcbiAgICBvdXRbMl0gPSBhWzJdO1xuICAgIG91dFszXSA9IGFbM107XG4gICAgb3V0WzRdID0gYVs0XTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIG91dFs2XSA9IGFbNl07XG4gICAgb3V0WzddID0gYVs3XTtcbiAgICBvdXRbOF0gPSBhWzhdO1xuICAgIG91dFs5XSA9IGFbOV07XG4gICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgIG91dFsxMV0gPSBhWzExXTtcbiAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5jb3B5ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbNF0gPSBhWzRdO1xuICAgIG91dFs1XSA9IGFbNV07XG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBTZXQgYSBtYXQ0IHRvIHRoZSBpZGVudGl0eSBtYXRyaXhcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmlkZW50aXR5ID0gZnVuY3Rpb24ob3V0KSB7XG4gICAgb3V0WzBdID0gMTtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IDE7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IDA7XG4gICAgb3V0WzldID0gMDtcbiAgICBvdXRbMTBdID0gMTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gMDtcbiAgICBvdXRbMTVdID0gMTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQudHJhbnNwb3NlID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgLy8gSWYgd2UgYXJlIHRyYW5zcG9zaW5nIG91cnNlbHZlcyB3ZSBjYW4gc2tpcCBhIGZldyBzdGVwcyBidXQgaGF2ZSB0byBjYWNoZSBzb21lIHZhbHVlc1xuICAgIGlmIChvdXQgPT09IGEpIHtcbiAgICAgICAgdmFyIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgICAgICBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGEwMTtcbiAgICAgICAgb3V0WzZdID0gYVs5XTtcbiAgICAgICAgb3V0WzddID0gYVsxM107XG4gICAgICAgIG91dFs4XSA9IGEwMjtcbiAgICAgICAgb3V0WzldID0gYTEyO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhMDM7XG4gICAgICAgIG91dFsxM10gPSBhMTM7XG4gICAgICAgIG91dFsxNF0gPSBhMjM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0WzBdID0gYVswXTtcbiAgICAgICAgb3V0WzFdID0gYVs0XTtcbiAgICAgICAgb3V0WzJdID0gYVs4XTtcbiAgICAgICAgb3V0WzNdID0gYVsxMl07XG4gICAgICAgIG91dFs0XSA9IGFbMV07XG4gICAgICAgIG91dFs1XSA9IGFbNV07XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhWzJdO1xuICAgICAgICBvdXRbOV0gPSBhWzZdO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzEyXSA9IGFbM107XG4gICAgICAgIG91dFsxM10gPSBhWzddO1xuICAgICAgICBvdXRbMTRdID0gYVsxMV07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl0sIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sIGExMSA9IGFbNV0sIGExMiA9IGFbNl0sIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sIGEyMSA9IGFbOV0sIGEyMiA9IGFbMTBdLCBhMjMgPSBhWzExXSxcbiAgICAgICAgYTMwID0gYVsxMl0sIGEzMSA9IGFbMTNdLCBhMzIgPSBhWzE0XSwgYTMzID0gYVsxNV0sXG5cbiAgICAgICAgYjAwID0gYTAwICogYTExIC0gYTAxICogYTEwLFxuICAgICAgICBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTAsXG4gICAgICAgIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMCxcbiAgICAgICAgYjAzID0gYTAxICogYTEyIC0gYTAyICogYTExLFxuICAgICAgICBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTEsXG4gICAgICAgIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMixcbiAgICAgICAgYjA2ID0gYTIwICogYTMxIC0gYTIxICogYTMwLFxuICAgICAgICBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzAsXG4gICAgICAgIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMCxcbiAgICAgICAgYjA5ID0gYTIxICogYTMyIC0gYTIyICogYTMxLFxuICAgICAgICBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzEsXG4gICAgICAgIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMixcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgICAgIGRldCA9IGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcblxuICAgIGlmICghZGV0KSB7IFxuICAgICAgICByZXR1cm4gbnVsbDsgXG4gICAgfVxuICAgIGRldCA9IDEuMCAvIGRldDtcblxuICAgIG91dFswXSA9IChhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDkpICogZGV0O1xuICAgIG91dFsxXSA9IChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0O1xuICAgIG91dFsyXSA9IChhMzEgKiBiMDUgLSBhMzIgKiBiMDQgKyBhMzMgKiBiMDMpICogZGV0O1xuICAgIG91dFszXSA9IChhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMpICogZGV0O1xuICAgIG91dFs0XSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICAgIG91dFs1XSA9IChhMDAgKiBiMTEgLSBhMDIgKiBiMDggKyBhMDMgKiBiMDcpICogZGV0O1xuICAgIG91dFs2XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICAgIG91dFs3XSA9IChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0O1xuICAgIG91dFs4XSA9IChhMTAgKiBiMTAgLSBhMTEgKiBiMDggKyBhMTMgKiBiMDYpICogZGV0O1xuICAgIG91dFs5XSA9IChhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYpICogZGV0O1xuICAgIG91dFsxMF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTFdID0gKGEyMSAqIGIwMiAtIGEyMCAqIGIwNCAtIGEyMyAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzEyXSA9IChhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYpICogZGV0O1xuICAgIG91dFsxM10gPSAoYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2KSAqIGRldDtcbiAgICBvdXRbMTRdID0gKGEzMSAqIGIwMSAtIGEzMCAqIGIwMyAtIGEzMiAqIGIwMCkgKiBkZXQ7XG4gICAgb3V0WzE1XSA9IChhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApICogZGV0O1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgYWRqdWdhdGUgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LmFkam9pbnQgPSBmdW5jdGlvbihvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XTtcblxuICAgIG91dFswXSAgPSAgKGExMSAqIChhMjIgKiBhMzMgLSBhMjMgKiBhMzIpIC0gYTIxICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgKyBhMzEgKiAoYTEyICogYTIzIC0gYTEzICogYTIyKSk7XG4gICAgb3V0WzFdICA9IC0oYTAxICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjEgKiAoYTAyICogYTMzIC0gYTAzICogYTMyKSArIGEzMSAqIChhMDIgKiBhMjMgLSBhMDMgKiBhMjIpKTtcbiAgICBvdXRbMl0gID0gIChhMDEgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSAtIGExMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGExMyAtIGEwMyAqIGExMikpO1xuICAgIG91dFszXSAgPSAtKGEwMSAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpIC0gYTExICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikgKyBhMjEgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzRdICA9IC0oYTEwICogKGEyMiAqIGEzMyAtIGEyMyAqIGEzMikgLSBhMjAgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSArIGEzMCAqIChhMTIgKiBhMjMgLSBhMTMgKiBhMjIpKTtcbiAgICBvdXRbNV0gID0gIChhMDAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMwICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikpO1xuICAgIG91dFs2XSAgPSAtKGEwMCAqIChhMTIgKiBhMzMgLSBhMTMgKiBhMzIpIC0gYTEwICogKGEwMiAqIGEzMyAtIGEwMyAqIGEzMikgKyBhMzAgKiAoYTAyICogYTEzIC0gYTAzICogYTEyKSk7XG4gICAgb3V0WzddICA9ICAoYTAwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTAgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgICBvdXRbOF0gID0gIChhMTAgKiAoYTIxICogYTMzIC0gYTIzICogYTMxKSAtIGEyMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpICsgYTMwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSkpO1xuICAgIG91dFs5XSAgPSAtKGEwMCAqIChhMjEgKiBhMzMgLSBhMjMgKiBhMzEpIC0gYTIwICogKGEwMSAqIGEzMyAtIGEwMyAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTIzIC0gYTAzICogYTIxKSk7XG4gICAgb3V0WzEwXSA9ICAoYTAwICogKGExMSAqIGEzMyAtIGExMyAqIGEzMSkgLSBhMTAgKiAoYTAxICogYTMzIC0gYTAzICogYTMxKSArIGEzMCAqIChhMDEgKiBhMTMgLSBhMDMgKiBhMTEpKTtcbiAgICBvdXRbMTFdID0gLShhMDAgKiAoYTExICogYTIzIC0gYTEzICogYTIxKSAtIGExMCAqIChhMDEgKiBhMjMgLSBhMDMgKiBhMjEpICsgYTIwICogKGEwMSAqIGExMyAtIGEwMyAqIGExMSkpO1xuICAgIG91dFsxMl0gPSAtKGExMCAqIChhMjEgKiBhMzIgLSBhMjIgKiBhMzEpIC0gYTIwICogKGExMSAqIGEzMiAtIGExMiAqIGEzMSkgKyBhMzAgKiAoYTExICogYTIyIC0gYTEyICogYTIxKSk7XG4gICAgb3V0WzEzXSA9ICAoYTAwICogKGEyMSAqIGEzMiAtIGEyMiAqIGEzMSkgLSBhMjAgKiAoYTAxICogYTMyIC0gYTAyICogYTMxKSArIGEzMCAqIChhMDEgKiBhMjIgLSBhMDIgKiBhMjEpKTtcbiAgICBvdXRbMTRdID0gLShhMDAgKiAoYTExICogYTMyIC0gYTEyICogYTMxKSAtIGExMCAqIChhMDEgKiBhMzIgLSBhMDIgKiBhMzEpICsgYTMwICogKGEwMSAqIGExMiAtIGEwMiAqIGExMSkpO1xuICAgIG91dFsxNV0gPSAgKGEwMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpIC0gYTEwICogKGEwMSAqIGEyMiAtIGEwMiAqIGEyMSkgKyBhMjAgKiAoYTAxICogYTEyIC0gYTAyICogYTExKSk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZGV0ZXJtaW5hbnQgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkZXRlcm1pbmFudCBvZiBhXG4gKi9cbm1hdDQuZGV0ZXJtaW5hbnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgcmV0dXJuIGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcbn07XG5cbi8qKlxuICogTXVsdGlwbGllcyB0d28gbWF0NCdzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHttYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0Lm11bHRpcGx5ID0gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdO1xuXG4gICAgLy8gQ2FjaGUgb25seSB0aGUgY3VycmVudCBsaW5lIG9mIHRoZSBzZWNvbmQgbWF0cml4XG4gICAgdmFyIGIwICA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107ICBcbiAgICBvdXRbMF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzFdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsyXSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbM10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbNF07IGIxID0gYls1XTsgYjIgPSBiWzZdOyBiMyA9IGJbN107XG4gICAgb3V0WzRdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs1XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbNl0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzddID0gYjAqYTAzICsgYjEqYTEzICsgYjIqYTIzICsgYjMqYTMzO1xuXG4gICAgYjAgPSBiWzhdOyBiMSA9IGJbOV07IGIyID0gYlsxMF07IGIzID0gYlsxMV07XG4gICAgb3V0WzhdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs5XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTBdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxMV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbMTJdOyBiMSA9IGJbMTNdOyBiMiA9IGJbMTRdOyBiMyA9IGJbMTVdO1xuICAgIG91dFsxMl0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzEzXSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTRdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxNV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cbm1hdDQubXVsID0gbWF0NC5tdWx0aXBseTtcblxuLyoqXG4gKiBUcmFuc2xhdGUgYSBtYXQ0IGJ5IHRoZSBnaXZlbiB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdmVjdG9yIHRvIHRyYW5zbGF0ZSBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChvdXQsIGEsIHYpIHtcbiAgICB2YXIgeCA9IHZbMF0sIHkgPSB2WzFdLCB6ID0gdlsyXSxcbiAgICAgICAgYTAwLCBhMDEsIGEwMiwgYTAzLFxuICAgICAgICBhMTAsIGExMSwgYTEyLCBhMTMsXG4gICAgICAgIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICAgIGlmIChhID09PSBvdXQpIHtcbiAgICAgICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzJdICogeCArIGFbNl0gKiB5ICsgYVsxMF0gKiB6ICsgYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICAgICAgYTEwID0gYVs0XTsgYTExID0gYVs1XTsgYTEyID0gYVs2XTsgYTEzID0gYVs3XTtcbiAgICAgICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFswXSA9IGEwMDsgb3V0WzFdID0gYTAxOyBvdXRbMl0gPSBhMDI7IG91dFszXSA9IGEwMztcbiAgICAgICAgb3V0WzRdID0gYTEwOyBvdXRbNV0gPSBhMTE7IG91dFs2XSA9IGExMjsgb3V0WzddID0gYTEzO1xuICAgICAgICBvdXRbOF0gPSBhMjA7IG91dFs5XSA9IGEyMTsgb3V0WzEwXSA9IGEyMjsgb3V0WzExXSA9IGEyMztcblxuICAgICAgICBvdXRbMTJdID0gYTAwICogeCArIGExMCAqIHkgKyBhMjAgKiB6ICsgYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhMDEgKiB4ICsgYTExICogeSArIGEyMSAqIHogKyBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYTAzICogeCArIGExMyAqIHkgKyBhMjMgKiB6ICsgYVsxNV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2NhbGVzIHRoZSBtYXQ0IGJ5IHRoZSBkaW1lbnNpb25zIGluIHRoZSBnaXZlbiB2ZWMzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdGhlIHZlYzMgdG8gc2NhbGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICoqL1xubWF0NC5zY2FsZSA9IGZ1bmN0aW9uKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV0sIHogPSB2WzJdO1xuXG4gICAgb3V0WzBdID0gYVswXSAqIHg7XG4gICAgb3V0WzFdID0gYVsxXSAqIHg7XG4gICAgb3V0WzJdID0gYVsyXSAqIHg7XG4gICAgb3V0WzNdID0gYVszXSAqIHg7XG4gICAgb3V0WzRdID0gYVs0XSAqIHk7XG4gICAgb3V0WzVdID0gYVs1XSAqIHk7XG4gICAgb3V0WzZdID0gYVs2XSAqIHk7XG4gICAgb3V0WzddID0gYVs3XSAqIHk7XG4gICAgb3V0WzhdID0gYVs4XSAqIHo7XG4gICAgb3V0WzldID0gYVs5XSAqIHo7XG4gICAgb3V0WzEwXSA9IGFbMTBdICogejtcbiAgICBvdXRbMTFdID0gYVsxMV0gKiB6O1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0NCBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGUgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQsIGF4aXMpIHtcbiAgICB2YXIgeCA9IGF4aXNbMF0sIHkgPSBheGlzWzFdLCB6ID0gYXhpc1syXSxcbiAgICAgICAgbGVuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiksXG4gICAgICAgIHMsIGMsIHQsXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjMsXG4gICAgICAgIGIwMCwgYjAxLCBiMDIsXG4gICAgICAgIGIxMCwgYjExLCBiMTIsXG4gICAgICAgIGIyMCwgYjIxLCBiMjI7XG5cbiAgICBpZiAoTWF0aC5hYnMobGVuKSA8IEdMTUFUX0VQU0lMT04pIHsgcmV0dXJuIG51bGw7IH1cbiAgICBcbiAgICBsZW4gPSAxIC8gbGVuO1xuICAgIHggKj0gbGVuO1xuICAgIHkgKj0gbGVuO1xuICAgIHogKj0gbGVuO1xuXG4gICAgcyA9IE1hdGguc2luKHJhZCk7XG4gICAgYyA9IE1hdGguY29zKHJhZCk7XG4gICAgdCA9IDEgLSBjO1xuXG4gICAgYTAwID0gYVswXTsgYTAxID0gYVsxXTsgYTAyID0gYVsyXTsgYTAzID0gYVszXTtcbiAgICBhMTAgPSBhWzRdOyBhMTEgPSBhWzVdOyBhMTIgPSBhWzZdOyBhMTMgPSBhWzddO1xuICAgIGEyMCA9IGFbOF07IGEyMSA9IGFbOV07IGEyMiA9IGFbMTBdOyBhMjMgPSBhWzExXTtcblxuICAgIC8vIENvbnN0cnVjdCB0aGUgZWxlbWVudHMgb2YgdGhlIHJvdGF0aW9uIG1hdHJpeFxuICAgIGIwMCA9IHggKiB4ICogdCArIGM7IGIwMSA9IHkgKiB4ICogdCArIHogKiBzOyBiMDIgPSB6ICogeCAqIHQgLSB5ICogcztcbiAgICBiMTAgPSB4ICogeSAqIHQgLSB6ICogczsgYjExID0geSAqIHkgKiB0ICsgYzsgYjEyID0geiAqIHkgKiB0ICsgeCAqIHM7XG4gICAgYjIwID0geCAqIHogKiB0ICsgeSAqIHM7IGIyMSA9IHkgKiB6ICogdCAtIHggKiBzOyBiMjIgPSB6ICogeiAqIHQgKyBjO1xuXG4gICAgLy8gUGVyZm9ybSByb3RhdGlvbi1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBiMDAgKyBhMTAgKiBiMDEgKyBhMjAgKiBiMDI7XG4gICAgb3V0WzFdID0gYTAxICogYjAwICsgYTExICogYjAxICsgYTIxICogYjAyO1xuICAgIG91dFsyXSA9IGEwMiAqIGIwMCArIGExMiAqIGIwMSArIGEyMiAqIGIwMjtcbiAgICBvdXRbM10gPSBhMDMgKiBiMDAgKyBhMTMgKiBiMDEgKyBhMjMgKiBiMDI7XG4gICAgb3V0WzRdID0gYTAwICogYjEwICsgYTEwICogYjExICsgYTIwICogYjEyO1xuICAgIG91dFs1XSA9IGEwMSAqIGIxMCArIGExMSAqIGIxMSArIGEyMSAqIGIxMjtcbiAgICBvdXRbNl0gPSBhMDIgKiBiMTAgKyBhMTIgKiBiMTEgKyBhMjIgKiBiMTI7XG4gICAgb3V0WzddID0gYTAzICogYjEwICsgYTEzICogYjExICsgYTIzICogYjEyO1xuICAgIG91dFs4XSA9IGEwMCAqIGIyMCArIGExMCAqIGIyMSArIGEyMCAqIGIyMjtcbiAgICBvdXRbOV0gPSBhMDEgKiBiMjAgKyBhMTEgKiBiMjEgKyBhMjEgKiBiMjI7XG4gICAgb3V0WzEwXSA9IGEwMiAqIGIyMCArIGExMiAqIGIyMSArIGEyMiAqIGIyMjtcbiAgICBvdXRbMTFdID0gYTAzICogYjIwICsgYTEzICogYjIxICsgYTIzICogYjIyO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5yb3RhdGVYID0gZnVuY3Rpb24gKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSxcbiAgICAgICAgYTIxID0gYVs5XSxcbiAgICAgICAgYTIyID0gYVsxMF0sXG4gICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgaWYgKGEgIT09IG91dCkgeyAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgICAgIG91dFswXSAgPSBhWzBdO1xuICAgICAgICBvdXRbMV0gID0gYVsxXTtcbiAgICAgICAgb3V0WzJdICA9IGFbMl07XG4gICAgICAgIG91dFszXSAgPSBhWzNdO1xuICAgICAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFs0XSA9IGExMCAqIGMgKyBhMjAgKiBzO1xuICAgIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICAgIG91dFs2XSA9IGExMiAqIGMgKyBhMjIgKiBzO1xuICAgIG91dFs3XSA9IGExMyAqIGMgKyBhMjMgKiBzO1xuICAgIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICAgIG91dFs5XSA9IGEyMSAqIGMgLSBhMTEgKiBzO1xuICAgIG91dFsxMF0gPSBhMjIgKiBjIC0gYTEyICogcztcbiAgICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMjAgPSBhWzhdLFxuICAgICAgICBhMjEgPSBhWzldLFxuICAgICAgICBhMjIgPSBhWzEwXSxcbiAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIHJvd3NcbiAgICAgICAgb3V0WzRdICA9IGFbNF07XG4gICAgICAgIG91dFs1XSAgPSBhWzVdO1xuICAgICAgICBvdXRbNl0gID0gYVs2XTtcbiAgICAgICAgb3V0WzddICA9IGFbN107XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyAtIGEyMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyAtIGEyMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyAtIGEyMyAqIHM7XG4gICAgb3V0WzhdID0gYTAwICogcyArIGEyMCAqIGM7XG4gICAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gICAgb3V0WzEwXSA9IGEwMiAqIHMgKyBhMjIgKiBjO1xuICAgIG91dFsxMV0gPSBhMDMgKiBzICsgYTIzICogYztcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQucm90YXRlWiA9IGZ1bmN0aW9uIChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGEwMCA9IGFbMF0sXG4gICAgICAgIGEwMSA9IGFbMV0sXG4gICAgICAgIGEwMiA9IGFbMl0sXG4gICAgICAgIGEwMyA9IGFbM10sXG4gICAgICAgIGExMCA9IGFbNF0sXG4gICAgICAgIGExMSA9IGFbNV0sXG4gICAgICAgIGExMiA9IGFbNl0sXG4gICAgICAgIGExMyA9IGFbN107XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgICAgIG91dFs4XSAgPSBhWzhdO1xuICAgICAgICBvdXRbOV0gID0gYVs5XTtcbiAgICAgICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgICAgICBvdXRbMTFdID0gYVsxMV07XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyArIGExMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyArIGExMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyArIGExMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyArIGExMyAqIHM7XG4gICAgb3V0WzRdID0gYTEwICogYyAtIGEwMCAqIHM7XG4gICAgb3V0WzVdID0gYTExICogYyAtIGEwMSAqIHM7XG4gICAgb3V0WzZdID0gYTEyICogYyAtIGEwMiAqIHM7XG4gICAgb3V0WzddID0gYTEzICogYyAtIGEwMyAqIHM7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiBhbmQgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIHZhciBxdWF0TWF0ID0gbWF0NC5jcmVhdGUoKTtcbiAqICAgICBxdWF0NC50b01hdDQocXVhdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5tdWx0aXBseShkZXN0LCBxdWF0TWF0KTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7dmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5mcm9tUm90YXRpb25UcmFuc2xhdGlvbiA9IGZ1bmN0aW9uIChvdXQsIHEsIHYpIHtcbiAgICAvLyBRdWF0ZXJuaW9uIG1hdGhcbiAgICB2YXIgeCA9IHFbMF0sIHkgPSBxWzFdLCB6ID0gcVsyXSwgdyA9IHFbM10sXG4gICAgICAgIHgyID0geCArIHgsXG4gICAgICAgIHkyID0geSArIHksXG4gICAgICAgIHoyID0geiArIHosXG5cbiAgICAgICAgeHggPSB4ICogeDIsXG4gICAgICAgIHh5ID0geCAqIHkyLFxuICAgICAgICB4eiA9IHggKiB6MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHl6ID0geSAqIHoyLFxuICAgICAgICB6eiA9IHogKiB6MixcbiAgICAgICAgd3ggPSB3ICogeDIsXG4gICAgICAgIHd5ID0gdyAqIHkyLFxuICAgICAgICB3eiA9IHcgKiB6MjtcblxuICAgIG91dFswXSA9IDEgLSAoeXkgKyB6eik7XG4gICAgb3V0WzFdID0geHkgKyB3ejtcbiAgICBvdXRbMl0gPSB4eiAtIHd5O1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0geHkgLSB3ejtcbiAgICBvdXRbNV0gPSAxIC0gKHh4ICsgenopO1xuICAgIG91dFs2XSA9IHl6ICsgd3g7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSB4eiArIHd5O1xuICAgIG91dFs5XSA9IHl6IC0gd3g7XG4gICAgb3V0WzEwXSA9IDEgLSAoeHggKyB5eSk7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IHZbMF07XG4gICAgb3V0WzEzXSA9IHZbMV07XG4gICAgb3V0WzE0XSA9IHZbMl07XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbm1hdDQuZnJvbVF1YXQgPSBmdW5jdGlvbiAob3V0LCBxKSB7XG4gICAgdmFyIHggPSBxWzBdLCB5ID0gcVsxXSwgeiA9IHFbMl0sIHcgPSBxWzNdLFxuICAgICAgICB4MiA9IHggKyB4LFxuICAgICAgICB5MiA9IHkgKyB5LFxuICAgICAgICB6MiA9IHogKyB6LFxuXG4gICAgICAgIHh4ID0geCAqIHgyLFxuICAgICAgICB5eCA9IHkgKiB4MixcbiAgICAgICAgeXkgPSB5ICogeTIsXG4gICAgICAgIHp4ID0geiAqIHgyLFxuICAgICAgICB6eSA9IHogKiB5MixcbiAgICAgICAgenogPSB6ICogejIsXG4gICAgICAgIHd4ID0gdyAqIHgyLFxuICAgICAgICB3eSA9IHcgKiB5MixcbiAgICAgICAgd3ogPSB3ICogejI7XG5cbiAgICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgICBvdXRbMV0gPSB5eCArIHd6O1xuICAgIG91dFsyXSA9IHp4IC0gd3k7XG4gICAgb3V0WzNdID0gMDtcblxuICAgIG91dFs0XSA9IHl4IC0gd3o7XG4gICAgb3V0WzVdID0gMSAtIHh4IC0geno7XG4gICAgb3V0WzZdID0genkgKyB3eDtcbiAgICBvdXRbN10gPSAwO1xuXG4gICAgb3V0WzhdID0genggKyB3eTtcbiAgICBvdXRbOV0gPSB6eSAtIHd4O1xuICAgIG91dFsxMF0gPSAxIC0geHggLSB5eTtcbiAgICBvdXRbMTFdID0gMDtcblxuICAgIG91dFsxMl0gPSAwO1xuICAgIG91dFsxM10gPSAwO1xuICAgIG91dFsxNF0gPSAwO1xuICAgIG91dFsxNV0gPSAxO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgZnJ1c3R1bSBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtOdW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQuZnJ1c3R1bSA9IGZ1bmN0aW9uIChvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIHJsID0gMSAvIChyaWdodCAtIGxlZnQpLFxuICAgICAgICB0YiA9IDEgLyAodG9wIC0gYm90dG9tKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IChuZWFyICogMikgKiBybDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs1XSA9IChuZWFyICogMikgKiB0YjtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gKHJpZ2h0ICsgbGVmdCkgKiBybDtcbiAgICBvdXRbOV0gPSAodG9wICsgYm90dG9tKSAqIHRiO1xuICAgIG91dFsxMF0gPSAoZmFyICsgbmVhcikgKiBuZjtcbiAgICBvdXRbMTFdID0gLTE7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IChmYXIgKiBuZWFyICogMikgKiBuZjtcbiAgICBvdXRbMTVdID0gMDtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge251bWJlcn0gZm92eSBWZXJ0aWNhbCBmaWVsZCBvZiB2aWV3IGluIHJhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhc3BlY3QgQXNwZWN0IHJhdGlvLiB0eXBpY2FsbHkgdmlld3BvcnQgd2lkdGgvaGVpZ2h0XG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5tYXQ0LnBlcnNwZWN0aXZlID0gZnVuY3Rpb24gKG91dCwgZm92eSwgYXNwZWN0LCBuZWFyLCBmYXIpIHtcbiAgICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IGYgLyBhc3BlY3Q7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSBmO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxMV0gPSAtMTtcbiAgICBvdXRbMTJdID0gMDtcbiAgICBvdXRbMTNdID0gMDtcbiAgICBvdXRbMTRdID0gKDIgKiBmYXIgKiBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAwO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbm1hdDQub3J0aG8gPSBmdW5jdGlvbiAob3V0LCBsZWZ0LCByaWdodCwgYm90dG9tLCB0b3AsIG5lYXIsIGZhcikge1xuICAgIHZhciBsciA9IDEgLyAobGVmdCAtIHJpZ2h0KSxcbiAgICAgICAgYnQgPSAxIC8gKGJvdHRvbSAtIHRvcCksXG4gICAgICAgIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgICBvdXRbMF0gPSAtMiAqIGxyO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IDA7XG4gICAgb3V0WzVdID0gLTIgKiBidDtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gMDtcbiAgICBvdXRbOV0gPSAwO1xuICAgIG91dFsxMF0gPSAyICogbmY7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IChsZWZ0ICsgcmlnaHQpICogbHI7XG4gICAgb3V0WzEzXSA9ICh0b3AgKyBib3R0b20pICogYnQ7XG4gICAgb3V0WzE0XSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxNV0gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHt2ZWMzfSBleWUgUG9zaXRpb24gb2YgdGhlIHZpZXdlclxuICogQHBhcmFtIHt2ZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge3ZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xubWF0NC5sb29rQXQgPSBmdW5jdGlvbiAob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgICB2YXIgeDAsIHgxLCB4MiwgeTAsIHkxLCB5MiwgejAsIHoxLCB6MiwgbGVuLFxuICAgICAgICBleWV4ID0gZXllWzBdLFxuICAgICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgICBleWV6ID0gZXllWzJdLFxuICAgICAgICB1cHggPSB1cFswXSxcbiAgICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICAgIHVweiA9IHVwWzJdLFxuICAgICAgICBjZW50ZXJ4ID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJ5ID0gY2VudGVyWzFdLFxuICAgICAgICBjZW50ZXJ6ID0gY2VudGVyWzJdO1xuXG4gICAgaWYgKE1hdGguYWJzKGV5ZXggLSBjZW50ZXJ4KSA8IEdMTUFUX0VQU0lMT04gJiZcbiAgICAgICAgTWF0aC5hYnMoZXlleSAtIGNlbnRlcnkpIDwgR0xNQVRfRVBTSUxPTiAmJlxuICAgICAgICBNYXRoLmFicyhleWV6IC0gY2VudGVyeikgPCBHTE1BVF9FUFNJTE9OKSB7XG4gICAgICAgIHJldHVybiBtYXQ0LmlkZW50aXR5KG91dCk7XG4gICAgfVxuXG4gICAgejAgPSBleWV4IC0gY2VudGVyeDtcbiAgICB6MSA9IGV5ZXkgLSBjZW50ZXJ5O1xuICAgIHoyID0gZXlleiAtIGNlbnRlcno7XG5cbiAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KHowICogejAgKyB6MSAqIHoxICsgejIgKiB6Mik7XG4gICAgejAgKj0gbGVuO1xuICAgIHoxICo9IGxlbjtcbiAgICB6MiAqPSBsZW47XG5cbiAgICB4MCA9IHVweSAqIHoyIC0gdXB6ICogejE7XG4gICAgeDEgPSB1cHogKiB6MCAtIHVweCAqIHoyO1xuICAgIHgyID0gdXB4ICogejEgLSB1cHkgKiB6MDtcbiAgICBsZW4gPSBNYXRoLnNxcnQoeDAgKiB4MCArIHgxICogeDEgKyB4MiAqIHgyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB4MCA9IDA7XG4gICAgICAgIHgxID0gMDtcbiAgICAgICAgeDIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHgwICo9IGxlbjtcbiAgICAgICAgeDEgKj0gbGVuO1xuICAgICAgICB4MiAqPSBsZW47XG4gICAgfVxuXG4gICAgeTAgPSB6MSAqIHgyIC0gejIgKiB4MTtcbiAgICB5MSA9IHoyICogeDAgLSB6MCAqIHgyO1xuICAgIHkyID0gejAgKiB4MSAtIHoxICogeDA7XG5cbiAgICBsZW4gPSBNYXRoLnNxcnQoeTAgKiB5MCArIHkxICogeTEgKyB5MiAqIHkyKTtcbiAgICBpZiAoIWxlbikge1xuICAgICAgICB5MCA9IDA7XG4gICAgICAgIHkxID0gMDtcbiAgICAgICAgeTIgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxlbiA9IDEgLyBsZW47XG4gICAgICAgIHkwICo9IGxlbjtcbiAgICAgICAgeTEgKj0gbGVuO1xuICAgICAgICB5MiAqPSBsZW47XG4gICAgfVxuXG4gICAgb3V0WzBdID0geDA7XG4gICAgb3V0WzFdID0geTA7XG4gICAgb3V0WzJdID0gejA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSB4MTtcbiAgICBvdXRbNV0gPSB5MTtcbiAgICBvdXRbNl0gPSB6MTtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IHgyO1xuICAgIG91dFs5XSA9IHkyO1xuICAgIG91dFsxMF0gPSB6MjtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gLSh4MCAqIGV5ZXggKyB4MSAqIGV5ZXkgKyB4MiAqIGV5ZXopO1xuICAgIG91dFsxM10gPSAtKHkwICogZXlleCArIHkxICogZXlleSArIHkyICogZXlleik7XG4gICAgb3V0WzE0XSA9IC0oejAgKiBleWV4ICsgejEgKiBleWV5ICsgejIgKiBleWV6KTtcbiAgICBvdXRbMTVdID0gMTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBtYXQgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xubWF0NC5zdHIgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybiAnbWF0NCgnICsgYVswXSArICcsICcgKyBhWzFdICsgJywgJyArIGFbMl0gKyAnLCAnICsgYVszXSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhWzRdICsgJywgJyArIGFbNV0gKyAnLCAnICsgYVs2XSArICcsICcgKyBhWzddICsgJywgJyArXG4gICAgICAgICAgICAgICAgICAgIGFbOF0gKyAnLCAnICsgYVs5XSArICcsICcgKyBhWzEwXSArICcsICcgKyBhWzExXSArICcsICcgKyBcbiAgICAgICAgICAgICAgICAgICAgYVsxMl0gKyAnLCAnICsgYVsxM10gKyAnLCAnICsgYVsxNF0gKyAnLCAnICsgYVsxNV0gKyAnKSc7XG59O1xuXG4vKipcbiAqIFJldHVybnMgRnJvYmVuaXVzIG5vcm0gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gY2FsY3VsYXRlIEZyb2Jlbml1cyBub3JtIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBGcm9iZW5pdXMgbm9ybVxuICovXG5tYXQ0LmZyb2IgPSBmdW5jdGlvbiAoYSkge1xuICAgIHJldHVybihNYXRoLnNxcnQoTWF0aC5wb3coYVswXSwgMikgKyBNYXRoLnBvdyhhWzFdLCAyKSArIE1hdGgucG93KGFbMl0sIDIpICsgTWF0aC5wb3coYVszXSwgMikgKyBNYXRoLnBvdyhhWzRdLCAyKSArIE1hdGgucG93KGFbNV0sIDIpICsgTWF0aC5wb3coYVs2XSwgMikgKyBNYXRoLnBvdyhhWzZdLCAyKSArIE1hdGgucG93KGFbN10sIDIpICsgTWF0aC5wb3coYVs4XSwgMikgKyBNYXRoLnBvdyhhWzldLCAyKSArIE1hdGgucG93KGFbMTBdLCAyKSArIE1hdGgucG93KGFbMTFdLCAyKSArIE1hdGgucG93KGFbMTJdLCAyKSArIE1hdGgucG93KGFbMTNdLCAyKSArIE1hdGgucG93KGFbMTRdLCAyKSArIE1hdGgucG93KGFbMTVdLCAyKSApKVxufTtcblxuXG5pZih0eXBlb2YoZXhwb3J0cykgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZXhwb3J0cy5tYXQ0ID0gbWF0NDtcbn1cbjtcbi8qIENvcHlyaWdodCAoYykgMjAxMywgQnJhbmRvbiBKb25lcywgQ29saW4gTWFjS2VuemllIElWLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG5SZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gICogUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gXG4gICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cblRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxuQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4oSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XG5MT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbkFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4oSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xuU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuICovXG5cbi8qKlxuICogQGNsYXNzIFF1YXRlcm5pb25cbiAqIEBuYW1lIHF1YXRcbiAqL1xuXG52YXIgcXVhdCA9IHt9O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgcXVhdFxuICpcbiAqIEByZXR1cm5zIHtxdWF0fSBhIG5ldyBxdWF0ZXJuaW9uXG4gKi9cbnF1YXQuY3JlYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG91dCA9IG5ldyBHTE1BVF9BUlJBWV9UWVBFKDQpO1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogU2V0cyBhIHF1YXRlcm5pb24gdG8gcmVwcmVzZW50IHRoZSBzaG9ydGVzdCByb3RhdGlvbiBmcm9tIG9uZVxuICogdmVjdG9yIHRvIGFub3RoZXIuXG4gKlxuICogQm90aCB2ZWN0b3JzIGFyZSBhc3N1bWVkIHRvIGJlIHVuaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgaW5pdGlhbCB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgZGVzdGluYXRpb24gdmVjdG9yXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQucm90YXRpb25UbyA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdG1wdmVjMyA9IHZlYzMuY3JlYXRlKCk7XG4gICAgdmFyIHhVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygxLDAsMCk7XG4gICAgdmFyIHlVbml0VmVjMyA9IHZlYzMuZnJvbVZhbHVlcygwLDEsMCk7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBhLCBiKSB7XG4gICAgICAgIHZhciBkb3QgPSB2ZWMzLmRvdChhLCBiKTtcbiAgICAgICAgaWYgKGRvdCA8IC0wLjk5OTk5OSkge1xuICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB4VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgaWYgKHZlYzMubGVuZ3RoKHRtcHZlYzMpIDwgMC4wMDAwMDEpXG4gICAgICAgICAgICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCB5VW5pdFZlYzMsIGEpO1xuICAgICAgICAgICAgdmVjMy5ub3JtYWxpemUodG1wdmVjMywgdG1wdmVjMyk7XG4gICAgICAgICAgICBxdWF0LnNldEF4aXNBbmdsZShvdXQsIHRtcHZlYzMsIE1hdGguUEkpO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSBlbHNlIGlmIChkb3QgPiAwLjk5OTk5OSkge1xuICAgICAgICAgICAgb3V0WzBdID0gMDtcbiAgICAgICAgICAgIG91dFsxXSA9IDA7XG4gICAgICAgICAgICBvdXRbMl0gPSAwO1xuICAgICAgICAgICAgb3V0WzNdID0gMTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2ZWMzLmNyb3NzKHRtcHZlYzMsIGEsIGIpO1xuICAgICAgICAgICAgb3V0WzBdID0gdG1wdmVjM1swXTtcbiAgICAgICAgICAgIG91dFsxXSA9IHRtcHZlYzNbMV07XG4gICAgICAgICAgICBvdXRbMl0gPSB0bXB2ZWMzWzJdO1xuICAgICAgICAgICAgb3V0WzNdID0gMSArIGRvdDtcbiAgICAgICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIG91dCk7XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBzcGVjaWZpZWQgcXVhdGVybmlvbiB3aXRoIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlblxuICogYXhlcy4gRWFjaCBheGlzIGlzIGEgdmVjMyBhbmQgaXMgZXhwZWN0ZWQgdG8gYmUgdW5pdCBsZW5ndGggYW5kXG4gKiBwZXJwZW5kaWN1bGFyIHRvIGFsbCBvdGhlciBzcGVjaWZpZWQgYXhlcy5cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IHZpZXcgIHRoZSB2ZWN0b3IgcmVwcmVzZW50aW5nIHRoZSB2aWV3aW5nIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSByaWdodCB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJyaWdodFwiIGRpcmVjdGlvblxuICogQHBhcmFtIHt2ZWMzfSB1cCAgICB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJ1cFwiIGRpcmVjdGlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnNldEF4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hdHIgPSBtYXQzLmNyZWF0ZSgpO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgdmlldywgcmlnaHQsIHVwKSB7XG4gICAgICAgIG1hdHJbMF0gPSByaWdodFswXTtcbiAgICAgICAgbWF0clszXSA9IHJpZ2h0WzFdO1xuICAgICAgICBtYXRyWzZdID0gcmlnaHRbMl07XG5cbiAgICAgICAgbWF0clsxXSA9IHVwWzBdO1xuICAgICAgICBtYXRyWzRdID0gdXBbMV07XG4gICAgICAgIG1hdHJbN10gPSB1cFsyXTtcblxuICAgICAgICBtYXRyWzJdID0gLXZpZXdbMF07XG4gICAgICAgIG1hdHJbNV0gPSAtdmlld1sxXTtcbiAgICAgICAgbWF0cls4XSA9IC12aWV3WzJdO1xuXG4gICAgICAgIHJldHVybiBxdWF0Lm5vcm1hbGl6ZShvdXQsIHF1YXQuZnJvbU1hdDMob3V0LCBtYXRyKSk7XG4gICAgfTtcbn0pKCk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBxdWF0IGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7cXVhdH0gYSBuZXcgcXVhdGVybmlvblxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY2xvbmUgPSB2ZWM0LmNsb25lO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3F1YXR9IGEgbmV3IHF1YXRlcm5pb25cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmZyb21WYWx1ZXMgPSB2ZWM0LmZyb21WYWx1ZXM7XG5cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHF1YXQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBzb3VyY2UgcXVhdGVybmlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuY29weSA9IHZlYzQuY29weTtcblxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSBxdWF0IHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB3IFcgY29tcG9uZW50XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zZXQgPSB2ZWM0LnNldDtcblxuLyoqXG4gKiBTZXQgYSBxdWF0IHRvIHRoZSBpZGVudGl0eSBxdWF0ZXJuaW9uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaWRlbnRpdHkgPSBmdW5jdGlvbihvdXQpIHtcbiAgICBvdXRbMF0gPSAwO1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAxO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFNldHMgYSBxdWF0IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFuZCByb3RhdGlvbiBheGlzLFxuICogdGhlbiByZXR1cm5zIGl0LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIGFyb3VuZCB3aGljaCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqKi9cbnF1YXQuc2V0QXhpc0FuZ2xlID0gZnVuY3Rpb24ob3V0LCBheGlzLCByYWQpIHtcbiAgICByYWQgPSByYWQgKiAwLjU7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICAgIG91dFswXSA9IHMgKiBheGlzWzBdO1xuICAgIG91dFsxXSA9IHMgKiBheGlzWzFdO1xuICAgIG91dFsyXSA9IHMgKiBheGlzWzJdO1xuICAgIG91dFszXSA9IE1hdGguY29zKHJhZCk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQWRkcyB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmFkZCA9IHZlYzQuYWRkO1xuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQubXVsdGlwbHkgPSBmdW5jdGlvbihvdXQsIGEsIGIpIHtcbiAgICB2YXIgYXggPSBhWzBdLCBheSA9IGFbMV0sIGF6ID0gYVsyXSwgYXcgPSBhWzNdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdLCBidyA9IGJbM107XG5cbiAgICBvdXRbMF0gPSBheCAqIGJ3ICsgYXcgKiBieCArIGF5ICogYnogLSBheiAqIGJ5O1xuICAgIG91dFsxXSA9IGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieDtcbiAgICBvdXRbM10gPSBhdyAqIGJ3IC0gYXggKiBieCAtIGF5ICogYnkgLSBheiAqIGJ6O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5tdWx0aXBseX1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0Lm11bCA9IHF1YXQubXVsdGlwbHk7XG5cbi8qKlxuICogU2NhbGVzIGEgcXVhdCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zY2FsZSA9IHZlYzQuc2NhbGU7XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVggPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ4ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYng7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF6ICogYng7XG4gICAgb3V0WzJdID0gYXogKiBidyAtIGF5ICogYng7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYng7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBZIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVkgPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ5ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyAtIGF6ICogYnk7XG4gICAgb3V0WzFdID0gYXkgKiBidyArIGF3ICogYnk7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF4ICogYnk7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF5ICogYnk7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBaIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LnJvdGF0ZVogPSBmdW5jdGlvbiAob3V0LCBhLCByYWQpIHtcbiAgICByYWQgKj0gMC41OyBcblxuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLCBhdyA9IGFbM10sXG4gICAgICAgIGJ6ID0gTWF0aC5zaW4ocmFkKSwgYncgPSBNYXRoLmNvcyhyYWQpO1xuXG4gICAgb3V0WzBdID0gYXggKiBidyArIGF5ICogYno7XG4gICAgb3V0WzFdID0gYXkgKiBidyAtIGF4ICogYno7XG4gICAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYno7XG4gICAgb3V0WzNdID0gYXcgKiBidyAtIGF6ICogYno7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgVyBjb21wb25lbnQgb2YgYSBxdWF0IGZyb20gdGhlIFgsIFksIGFuZCBaIGNvbXBvbmVudHMuXG4gKiBBc3N1bWVzIHRoYXQgcXVhdGVybmlvbiBpcyAxIHVuaXQgaW4gbGVuZ3RoLlxuICogQW55IGV4aXN0aW5nIFcgY29tcG9uZW50IHdpbGwgYmUgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBXIGNvbXBvbmVudCBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5xdWF0LmNhbGN1bGF0ZVcgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl07XG5cbiAgICBvdXRbMF0gPSB4O1xuICAgIG91dFsxXSA9IHk7XG4gICAgb3V0WzJdID0gejtcbiAgICBvdXRbM10gPSAtTWF0aC5zcXJ0KE1hdGguYWJzKDEuMCAtIHggKiB4IC0geSAqIHkgLSB6ICogeikpO1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byBxdWF0J3NcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmRvdCA9IHZlYzQuZG90O1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3F1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7cXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlcnAgPSB2ZWM0LmxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuc2xlcnAgPSBmdW5jdGlvbiAob3V0LCBhLCBiLCB0KSB7XG4gICAgLy8gYmVuY2htYXJrczpcbiAgICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuXG4gICAgdmFyIGF4ID0gYVswXSwgYXkgPSBhWzFdLCBheiA9IGFbMl0sIGF3ID0gYVszXSxcbiAgICAgICAgYnggPSBiWzBdLCBieSA9IGJbMV0sIGJ6ID0gYlsyXSwgYncgPSBiWzNdO1xuXG4gICAgdmFyICAgICAgICBvbWVnYSwgY29zb20sIHNpbm9tLCBzY2FsZTAsIHNjYWxlMTtcblxuICAgIC8vIGNhbGMgY29zaW5lXG4gICAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3O1xuICAgIC8vIGFkanVzdCBzaWducyAoaWYgbmVjZXNzYXJ5KVxuICAgIGlmICggY29zb20gPCAwLjAgKSB7XG4gICAgICAgIGNvc29tID0gLWNvc29tO1xuICAgICAgICBieCA9IC0gYng7XG4gICAgICAgIGJ5ID0gLSBieTtcbiAgICAgICAgYnogPSAtIGJ6O1xuICAgICAgICBidyA9IC0gYnc7XG4gICAgfVxuICAgIC8vIGNhbGN1bGF0ZSBjb2VmZmljaWVudHNcbiAgICBpZiAoICgxLjAgLSBjb3NvbSkgPiAwLjAwMDAwMSApIHtcbiAgICAgICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgICAgIG9tZWdhICA9IE1hdGguYWNvcyhjb3NvbSk7XG4gICAgICAgIHNpbm9tICA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgc2NhbGUwID0gTWF0aC5zaW4oKDEuMCAtIHQpICogb21lZ2EpIC8gc2lub207XG4gICAgICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbTtcbiAgICB9IGVsc2UgeyAgICAgICAgXG4gICAgICAgIC8vIFwiZnJvbVwiIGFuZCBcInRvXCIgcXVhdGVybmlvbnMgYXJlIHZlcnkgY2xvc2UgXG4gICAgICAgIC8vICAuLi4gc28gd2UgY2FuIGRvIGEgbGluZWFyIGludGVycG9sYXRpb25cbiAgICAgICAgc2NhbGUwID0gMS4wIC0gdDtcbiAgICAgICAgc2NhbGUxID0gdDtcbiAgICB9XG4gICAgLy8gY2FsY3VsYXRlIGZpbmFsIHZhbHVlc1xuICAgIG91dFswXSA9IHNjYWxlMCAqIGF4ICsgc2NhbGUxICogYng7XG4gICAgb3V0WzFdID0gc2NhbGUwICogYXkgKyBzY2FsZTEgKiBieTtcbiAgICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6O1xuICAgIG91dFszXSA9IHNjYWxlMCAqIGF3ICsgc2NhbGUxICogYnc7XG4gICAgXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgaW52ZXJzZSBvZiBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBpbnZlcnNlIG9mXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbnF1YXQuaW52ZXJ0ID0gZnVuY3Rpb24ob3V0LCBhKSB7XG4gICAgdmFyIGEwID0gYVswXSwgYTEgPSBhWzFdLCBhMiA9IGFbMl0sIGEzID0gYVszXSxcbiAgICAgICAgZG90ID0gYTAqYTAgKyBhMSphMSArIGEyKmEyICsgYTMqYTMsXG4gICAgICAgIGludkRvdCA9IGRvdCA/IDEuMC9kb3QgOiAwO1xuICAgIFxuICAgIC8vIFRPRE86IFdvdWxkIGJlIGZhc3RlciB0byByZXR1cm4gWzAsMCwwLDBdIGltbWVkaWF0ZWx5IGlmIGRvdCA9PSAwXG5cbiAgICBvdXRbMF0gPSAtYTAqaW52RG90O1xuICAgIG91dFsxXSA9IC1hMSppbnZEb3Q7XG4gICAgb3V0WzJdID0gLWEyKmludkRvdDtcbiAgICBvdXRbM10gPSBhMyppbnZEb3Q7XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY29uanVnYXRlIG9mIGEgcXVhdFxuICogSWYgdGhlIHF1YXRlcm5pb24gaXMgbm9ybWFsaXplZCwgdGhpcyBmdW5jdGlvbiBpcyBmYXN0ZXIgdGhhbiBxdWF0LmludmVyc2UgYW5kIHByb2R1Y2VzIHRoZSBzYW1lIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSBjb25qdWdhdGUgb2ZcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xucXVhdC5jb25qdWdhdGUgPSBmdW5jdGlvbiAob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF07XG4gICAgb3V0WzFdID0gLWFbMV07XG4gICAgb3V0WzJdID0gLWFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubGVuZ3RoID0gdmVjNC5sZW5ndGg7XG5cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBxdWF0Lmxlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG5xdWF0LmxlbiA9IHF1YXQubGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKiBAZnVuY3Rpb25cbiAqL1xucXVhdC5zcXVhcmVkTGVuZ3RoID0gdmVjNC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5zcXVhcmVkTGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuc3FyTGVuID0gcXVhdC5zcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7cXVhdH0gYSBxdWF0ZXJuaW9uIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQubm9ybWFsaXplID0gdmVjNC5ub3JtYWxpemU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHF1YXRlcm5pb24gZnJvbSB0aGUgZ2l2ZW4gM3gzIHJvdGF0aW9uIG1hdHJpeC5cbiAqXG4gKiBOT1RFOiBUaGUgcmVzdWx0YW50IHF1YXRlcm5pb24gaXMgbm90IG5vcm1hbGl6ZWQsIHNvIHlvdSBzaG91bGQgYmUgc3VyZVxuICogdG8gcmVub3JtYWxpemUgdGhlIHF1YXRlcm5pb24geW91cnNlbGYgd2hlcmUgbmVjZXNzYXJ5LlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHttYXQzfSBtIHJvdGF0aW9uIG1hdHJpeFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cbnF1YXQuZnJvbU1hdDMgPSBmdW5jdGlvbihvdXQsIG0pIHtcbiAgICAvLyBBbGdvcml0aG0gaW4gS2VuIFNob2VtYWtlJ3MgYXJ0aWNsZSBpbiAxOTg3IFNJR0dSQVBIIGNvdXJzZSBub3Rlc1xuICAgIC8vIGFydGljbGUgXCJRdWF0ZXJuaW9uIENhbGN1bHVzIGFuZCBGYXN0IEFuaW1hdGlvblwiLlxuICAgIHZhciBmVHJhY2UgPSBtWzBdICsgbVs0XSArIG1bOF07XG4gICAgdmFyIGZSb290O1xuXG4gICAgaWYgKCBmVHJhY2UgPiAwLjAgKSB7XG4gICAgICAgIC8vIHx3fCA+IDEvMiwgbWF5IGFzIHdlbGwgY2hvb3NlIHcgPiAxLzJcbiAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMS4wKTsgIC8vIDJ3XG4gICAgICAgIG91dFszXSA9IDAuNSAqIGZSb290O1xuICAgICAgICBmUm9vdCA9IDAuNS9mUm9vdDsgIC8vIDEvKDR3KVxuICAgICAgICBvdXRbMF0gPSAobVs3XS1tWzVdKSpmUm9vdDtcbiAgICAgICAgb3V0WzFdID0gKG1bMl0tbVs2XSkqZlJvb3Q7XG4gICAgICAgIG91dFsyXSA9IChtWzNdLW1bMV0pKmZSb290O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHx3fCA8PSAxLzJcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBpZiAoIG1bNF0gPiBtWzBdIClcbiAgICAgICAgICBpID0gMTtcbiAgICAgICAgaWYgKCBtWzhdID4gbVtpKjMraV0gKVxuICAgICAgICAgIGkgPSAyO1xuICAgICAgICB2YXIgaiA9IChpKzEpJTM7XG4gICAgICAgIHZhciBrID0gKGkrMiklMztcbiAgICAgICAgXG4gICAgICAgIGZSb290ID0gTWF0aC5zcXJ0KG1baSozK2ldLW1baiozK2pdLW1bayozK2tdICsgMS4wKTtcbiAgICAgICAgb3V0W2ldID0gMC41ICogZlJvb3Q7XG4gICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7XG4gICAgICAgIG91dFszXSA9IChtW2sqMytqXSAtIG1baiozK2tdKSAqIGZSb290O1xuICAgICAgICBvdXRbal0gPSAobVtqKjMraV0gKyBtW2kqMytqXSkgKiBmUm9vdDtcbiAgICAgICAgb3V0W2tdID0gKG1bayozK2ldICsgbVtpKjMra10pICogZlJvb3Q7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBxdWF0ZW5pb25cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IHZlYyB2ZWN0b3IgdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHZlY3RvclxuICovXG5xdWF0LnN0ciA9IGZ1bmN0aW9uIChhKSB7XG4gICAgcmV0dXJuICdxdWF0KCcgKyBhWzBdICsgJywgJyArIGFbMV0gKyAnLCAnICsgYVsyXSArICcsICcgKyBhWzNdICsgJyknO1xufTtcblxuaWYodHlwZW9mKGV4cG9ydHMpICE9PSAndW5kZWZpbmVkJykge1xuICAgIGV4cG9ydHMucXVhdCA9IHF1YXQ7XG59XG47XG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbiAgfSkoc2hpbS5leHBvcnRzKTtcbn0pKHRoaXMpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBjb25zdGFudCh2YWx1ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVOdW1iZXIoYSwgYiwgdCkge1xuICAgIHJldHVybiAoYSAqICgxIC0gdCkpICsgKGIgKiB0KTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVBcnJheShhLCBiLCB0KSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBpbnRlcnBvbGF0ZU51bWJlcihhW2ldLCBiW2ldLCB0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0c1snaW50ZXJwb2xhdGVkJ10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzLFxuICAgICAgICBiYXNlID0gZi5iYXNlIHx8IDEsXG4gICAgICAgIGludGVycG9sYXRlID0gQXJyYXkuaXNBcnJheShzdG9wc1swXVsxXSkgPyBpbnRlcnBvbGF0ZUFycmF5IDogaW50ZXJwb2xhdGVOdW1iZXI7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oeikge1xuICAgICAgICAvLyBmaW5kIHRoZSB0d28gc3RvcHMgd2hpY2ggdGhlIGN1cnJlbnQgeiBpcyBiZXR3ZWVuXG4gICAgICAgIHZhciBsb3csIGhpZ2g7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0b3AgPSBzdG9wc1tpXTtcblxuICAgICAgICAgICAgaWYgKHN0b3BbMF0gPD0geikge1xuICAgICAgICAgICAgICAgIGxvdyA9IHN0b3A7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdG9wWzBdID4geikge1xuICAgICAgICAgICAgICAgIGhpZ2ggPSBzdG9wO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxvdyAmJiBoaWdoKSB7XG4gICAgICAgICAgICB2YXIgem9vbURpZmYgPSBoaWdoWzBdIC0gbG93WzBdLFxuICAgICAgICAgICAgICAgIHpvb21Qcm9ncmVzcyA9IHogLSBsb3dbMF0sXG5cbiAgICAgICAgICAgICAgICB0ID0gYmFzZSA9PT0gMSA/XG4gICAgICAgICAgICAgICAgem9vbVByb2dyZXNzIC8gem9vbURpZmYgOlxuICAgICAgICAgICAgICAgIChNYXRoLnBvdyhiYXNlLCB6b29tUHJvZ3Jlc3MpIC0gMSkgLyAoTWF0aC5wb3coYmFzZSwgem9vbURpZmYpIC0gMSk7XG5cbiAgICAgICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZShsb3dbMV0sIGhpZ2hbMV0sIHQpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAobG93KSB7XG4gICAgICAgICAgICByZXR1cm4gbG93WzFdO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoaGlnaCkge1xuICAgICAgICAgICAgcmV0dXJuIGhpZ2hbMV07XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuZXhwb3J0c1sncGllY2V3aXNlLWNvbnN0YW50J10gPSBmdW5jdGlvbihmKSB7XG4gICAgaWYgKCFmLnN0b3BzKSB7XG4gICAgICAgIHJldHVybiBjb25zdGFudChmKTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcHMgPSBmLnN0b3BzO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHopIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHN0b3BzW2ldWzBdID4geikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9wc1tpID09PSAwID8gMCA6IGkgLSAxXVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdG9wc1tzdG9wcy5sZW5ndGggLSAxXVsxXTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVmZXJlbmNlID0gcmVxdWlyZSgnLi4vLi4vcmVmZXJlbmNlL2xhdGVzdC5qcycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9wYXJzZWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHlsZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZShzdHlsZSwgcmVmZXJlbmNlKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYXJzZUNTU0NvbG9yID0gcmVxdWlyZSgnY3NzY29sb3JwYXJzZXInKS5wYXJzZUNTU0NvbG9yO1xudmFyIGZvcm1hdCA9IHJlcXVpcmUoJ3V0aWwnKS5mb3JtYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3R5bGUsIHJlZmVyZW5jZSkge1xuXG4gICAgdmFyIGNvbnN0YW50cyA9IHN0eWxlLmNvbnN0YW50cyB8fCB7fSxcbiAgICAgICAgbGF5ZXJzID0ge30sXG4gICAgICAgIGVycm9ycyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZXJyb3Ioa2V5LCB2YWwgLyosIG1lc3NhZ2UsIC4uLiovKSB7XG4gICAgICAgIHZhciBlcnIgPSB7XG4gICAgICAgICAgICBtZXNzYWdlOiAoa2V5ID8ga2V5ICsgJzogJyA6ICcnKSArXG4gICAgICAgICAgICBmb3JtYXQuYXBwbHkoZm9ybWF0LCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsLl9fbGluZV9fKSB7XG4gICAgICAgICAgICBlcnIubGluZSA9IHZhbC5fX2xpbmVfXztcbiAgICAgICAgfVxuXG4gICAgICAgIGVycm9ycy5wdXNoKGVycik7XG4gICAgfVxuXG4gICAgLy8gTWFpbiByZWN1cnNpdmUgdmFsaWRhdGlvbiBmdW5jdGlvbi4gVHJhY2tzOlxuICAgIC8vXG4gICAgLy8gLSBrZXk6IHN0cmluZyByZXByZXNlbnRpbmcgbG9jYXRpb24gb2YgdmFsaWRhdGlvbiBpbiBzdHlsZSB0cmVlLiBVc2VkIG9ubHlcbiAgICAvLyAgIGZvciBtb3JlIGluZm9ybWF0aXZlIGVycm9yIHJlcG9ydGluZy5cbiAgICAvLyAtIHZhbDogY3VycmVudCB2YWx1ZSBmcm9tIHN0eWxlIGJlaW5nIGV2YWx1YXRlZC4gTWF5IGJlIGFueXRoaW5nIGZyb20gYVxuICAgIC8vICAgaGlnaCBsZXZlbCBvYmplY3QgdGhhdCBuZWVkcyB0byBiZSBkZXNjZW5kZWQgaW50byBkZWVwZXIgb3IgYSBzaW1wbGVcbiAgICAvLyAgIHNjYWxhciB2YWx1ZS5cbiAgICAvLyAtIHNwZWM6IGN1cnJlbnQgc3BlYyBiZWluZyBldmFsdWF0ZWQuIFRyYWNrcyB2YWwuXG4gICAgLy9cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcblxuICAgICAgICAvLyBDb25zdGFudHNcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIHZhbFswXSA9PT0gJ0AnKSB7XG4gICAgICAgICAgICBpZiAoISh2YWwgaW4gY29uc3RhbnRzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2NvbnN0YW50IFwiJXNcIiBub3QgZm91bmQnLCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsID0gY29uc3RhbnRzW3ZhbF07XG4gICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRnVuY3Rpb25zXG4gICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uICYmIHR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRhdGUuZnVuY3Rpb24oa2V5LCB2YWwsIHNwZWMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNwZWMudHlwZSkge1xuICAgICAgICAgICAgdmFyIHZhbGlkYXRvciA9IHZhbGlkYXRlW3NwZWMudHlwZV07XG4gICAgICAgICAgICBpZiAodmFsaWRhdG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbGlkYXRvcihrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzcGVjID0gcmVmZXJlbmNlW3NwZWMudHlwZV07XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHNwZWMpO1xuICAgIH1cblxuICAgIHZhbGlkYXRlLmNvbnN0YW50cyA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mXyh2YWwpO1xuICAgICAgICBpZiAodHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ29iamVjdCBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGsgaW4gdmFsKSB7XG4gICAgICAgICAgICBpZiAoa1swXSAhPT0gJ0AnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJy4nICsgaywgdmFsW2tdLCAnY29uc3RhbnRzIG11c3Qgc3RhcnQgd2l0aCBcIkBcIicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLnNvdXJjZSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnXCJ0eXBlXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgICAgICBjYXNlICdyYXN0ZXInOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV90aWxlKTtcblxuICAgICAgICAgICAgICAgIGlmICgndXJsJyBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChbJ3R5cGUnLCAndXJsJywgJ3RpbGVTaXplJ10uaW5kZXhPZihwcm9wKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXkgKyAnLicgKyBwcm9wLCB2YWxbcHJvcF0sICdhIHNvdXJjZSB3aXRoIGEgXCJ1cmxcIiBwcm9wZXJ0eSBtYXkgbm90IGluY2x1ZGUgYSBcIiVzXCIgcHJvcGVydHknLCBwcm9wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZ2VvanNvbic6XG4gICAgICAgICAgICAgICAgdmFsaWRhdGUub2JqZWN0KGtleSwgdmFsLCByZWZlcmVuY2Uuc291cmNlX2dlb2pzb24pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndmlkZW8nOlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLm9iamVjdChrZXksIHZhbCwgcmVmZXJlbmNlLnNvdXJjZV92aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJy50eXBlJywgdmFsLnR5cGUsIHt2YWx1ZXM6IFsndmVjdG9yJywgJ3Jhc3RlcicsICdnZW9qc29uJywgJ3ZpZGVvJ119KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YWxpZGF0ZS5sYXllciA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgIGlmICghdmFsLnR5cGUgJiYgIXZhbC5yZWYpIHtcbiAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnZWl0aGVyIFwidHlwZVwiIG9yIFwicmVmXCIgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eXBlID0gdW5idW5kbGUodmFsLnR5cGUpLFxuICAgICAgICAgICAgcmVmID0gdW5idW5kbGUodmFsLnJlZik7XG5cbiAgICAgICAgaWYgKHZhbC5pZCkge1xuICAgICAgICAgICAgaWYgKGxheWVyc1t2YWwuaWRdKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwuaWQsICdkdXBsaWNhdGUgbGF5ZXIgaWQgXCIlc1wiLCBwcmV2aW91c2x5IHVzZWQgYXQgbGluZSAlZCcsIHZhbC5pZCwgbGF5ZXJzW3ZhbC5pZF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsYXllcnNbdmFsLmlkXSA9IHZhbC5pZC5fX2xpbmVfXztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgncmVmJyBpbiB2YWwpIHtcbiAgICAgICAgICAgIFsndHlwZScsICdzb3VyY2UnLCAnc291cmNlLWxheWVyJywgJ2ZpbHRlcicsICdsYXlvdXQnXS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHAgaW4gdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsW3BdLCAnXCIlc1wiIGlzIHByb2hpYml0ZWQgZm9yIHJlZiBsYXllcnMnLCBwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHBhcmVudDtcblxuICAgICAgICAgICAgc3R5bGUubGF5ZXJzLmZvckVhY2goZnVuY3Rpb24obGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAobGF5ZXIuaWQgPT0gcmVmKSBwYXJlbnQgPSBsYXllcjtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBsYXllciBcIiVzXCIgbm90IGZvdW5kJywgcmVmKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50LnJlZikge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnJlZiwgJ3JlZiBjYW5ub3QgcmVmZXJlbmNlIGFub3RoZXIgcmVmIGxheWVyJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJlbnQudHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlICE9PSAnYmFja2dyb3VuZCcpIHtcbiAgICAgICAgICAgIGlmICghdmFsLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcInNvdXJjZVwiJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzb3VyY2UgPSBzdHlsZS5zb3VyY2VzW3ZhbC5zb3VyY2VdO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ3NvdXJjZSBcIiVzXCIgbm90IGZvdW5kJywgdmFsLnNvdXJjZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzb3VyY2UudHlwZSA9PSAndmVjdG9yJyAmJiB0eXBlID09ICdyYXN0ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLnNvdXJjZSwgJ2xheWVyIFwiJXNcIiByZXF1aXJlcyBhIHJhc3RlciBzb3VyY2UnLCB2YWwuaWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc291cmNlLnR5cGUgPT0gJ3Jhc3RlcicgJiYgdHlwZSAhPSAncmFzdGVyJykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbC5zb3VyY2UsICdsYXllciBcIiVzXCIgcmVxdWlyZXMgYSB2ZWN0b3Igc291cmNlJywgdmFsLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5sYXllciwge1xuICAgICAgICAgICAgZmlsdGVyOiB2YWxpZGF0ZS5maWx0ZXIsXG4gICAgICAgICAgICBsYXlvdXQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ2xheW91dF8nICsgdHlwZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGUgJiYgc3BlYyAmJiB2YWxpZGF0ZShrZXksIHZhbCwgc3BlYyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFpbnQ6IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNwZWMgPSByZWZlcmVuY2VbJ3BhaW50XycgKyB0eXBlXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZSAmJiBzcGVjICYmIHZhbGlkYXRlKGtleSwgdmFsLCBzcGVjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLm9iamVjdCA9IGZ1bmN0aW9uIChrZXksIHZhbCwgc3BlYywgdmFsaWRhdG9ycykge1xuICAgICAgICB2YWxpZGF0b3JzID0gdmFsaWRhdG9ycyB8fCB7fTtcblxuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdvYmplY3QgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBrIGluIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNwZWNrZXkgPSBrLnNwbGl0KCcuJylbMF07IC8vIHRyZWF0ICdwYWludC4qJyBhcyAncGFpbnQnXG4gICAgICAgICAgICB2YXIgZGVmID0gc3BlY1tzcGVja2V5XSB8fCBzcGVjWycqJ107XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHNwZWNrZXkubWF0Y2goL14oLiopLXRyYW5zaXRpb24kLyk7XG5cbiAgICAgICAgICAgIGlmIChkZWYpIHtcbiAgICAgICAgICAgICAgICAodmFsaWRhdG9yc1tzcGVja2V5XSB8fCB2YWxpZGF0ZSkoKGtleSA/IGtleSArICcuJyA6IGtleSkgKyBrLCB2YWxba10sIGRlZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zaXRpb24gJiYgc3BlY1t0cmFuc2l0aW9uWzFdXSAmJiBzcGVjW3RyYW5zaXRpb25bMV1dLnRyYW5zaXRpb24pIHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZSgoa2V5ID8ga2V5ICsgJy4nIDoga2V5KSArIGssIHZhbFtrXSwgcmVmZXJlbmNlLnRyYW5zaXRpb24pO1xuICAgICAgICAgICAgLy8gdG9sZXJhdGUgcm9vdC1sZXZlbCBleHRyYSBrZXlzICYgYXJiaXRyYXJ5IGxheWVyIHByb3BlcnRpZXNcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ICE9PSAnJyAmJiBrZXkuc3BsaXQoJy4nKS5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbFtrXSwgJ3Vua25vd24gcHJvcGVydHkgXCIlc1wiJywgayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBsIGluIHNwZWMpIHtcbiAgICAgICAgICAgIGlmIChzcGVjW2xdLnJlcXVpcmVkICYmIHNwZWNbbF1bJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIHZhbFtsXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwiJXNcIicsIGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmFycmF5ID0gZnVuY3Rpb24gKGtleSwgdmFsLCBzcGVjLCB2YWxpZGF0b3IpIHtcbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzcGVjLmxlbmd0aCAmJiB2YWwubGVuZ3RoICE9PSBzcGVjLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgbGVuZ3RoICVkIGV4cGVjdGVkLCBsZW5ndGggJWQgZm91bmQnLCBzcGVjLmxlbmd0aCwgdmFsLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdmFsdWUgPSB7XG4gICAgICAgICAgICBcInR5cGVcIjogc3BlYy52YWx1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChzdHlsZS52ZXJzaW9uIDwgNykge1xuICAgICAgICAgICAgdmFsdWUuZnVuY3Rpb24gPSBzcGVjLmZ1bmN0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZl8oc3BlYy52YWx1ZSkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHNwZWMudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgKHZhbGlkYXRvciB8fCB2YWxpZGF0ZSkoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZmlsdGVyID0gZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICAgICAgdmFyIHR5cGU7XG5cbiAgICAgICAgaWYgKHR5cGVvZl8odmFsKSAhPT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnYXJyYXkgZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZW9mXyh2YWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwubGVuZ3RoIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yKGtleSwgdmFsLCAnZmlsdGVyIGFycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCAxIGVsZW1lbnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1swXScsIHZhbFswXSwgcmVmZXJlbmNlLmZpbHRlcl9vcGVyYXRvcik7XG5cbiAgICAgICAgc3dpdGNoICh1bmJ1bmRsZSh2YWxbMF0pKSB7XG4gICAgICAgICAgICBjYXNlICc8JzpcbiAgICAgICAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID49IDIgJiYgdmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdcIiR0eXBlXCIgY2Fubm90IGJlIHVzZSB3aXRoIG9wZXJhdG9yIFwiJXNcIicsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnPT0nOlxuICAgICAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoICE9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdmaWx0ZXIgYXJyYXkgZm9yIG9wZXJhdG9yIFwiJXNcIiBtdXN0IGhhdmUgMyBlbGVtZW50cycsIHZhbFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnaW4nOlxuICAgICAgICAgICAgY2FzZSAnIWluJzpcbiAgICAgICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSB0eXBlb2ZfKHZhbFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ3N0cmluZyBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWxbMV1bMF0gPT09ICdAJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1sxXScsIHZhbFsxXSwgJ2ZpbHRlciBrZXkgY2Fubm90IGJlIGEgY29uc3RhbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gdHlwZW9mXyh2YWxbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsWzFdID09ICckdHlwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlLmVudW0oa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCByZWZlcmVuY2UuZ2VvbWV0cnlfdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgdmFsW2ldWzBdID09PSAnQCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbJyArIGkgKyAnXScsIHZhbFtpXSwgJ2ZpbHRlciB2YWx1ZSBjYW5ub3QgYmUgYSBjb25zdGFudCcpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgIT09ICdzdHJpbmcnICYmIHR5cGUgIT09ICdudW1iZXInICYmIHR5cGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldLCAnc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4gZXhwZWN0ZWQsICVzIGZvdW5kJywgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2FueSc6XG4gICAgICAgICAgICBjYXNlICdhbGwnOlxuICAgICAgICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHZhbC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZS5maWx0ZXIoa2V5ICsgJ1snICsgaSArICddJywgdmFsW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuZnVuY3Rpb24gPSBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICB2YWxpZGF0ZS5vYmplY3Qoa2V5LCB2YWwsIHJlZmVyZW5jZS5mdW5jdGlvbiwge1xuICAgICAgICAgICAgc3RvcHM6IGZ1bmN0aW9uIChrZXksIHZhbCwgYXJyYXlTcGVjKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RTdG9wID0gLUluZmluaXR5O1xuICAgICAgICAgICAgICAgIHZhbGlkYXRlLmFycmF5KGtleSwgdmFsLCBhcnJheVNwZWMsIGZ1bmN0aW9uIHZhbGlkYXRlU3RvcChrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mXyh2YWwpICE9PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3Ioa2V5LCB2YWwsICdhcnJheSBleHBlY3RlZCwgJXMgZm91bmQnLCB0eXBlb2ZfKHZhbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcihrZXksIHZhbCwgJ2FycmF5IGxlbmd0aCAlZCBleHBlY3RlZCwgbGVuZ3RoICVkIGZvdW5kJywgMiwgdmFsLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZShrZXkgKyAnWzBdJywgdmFsWzBdLCB7dHlwZTogJ251bWJlcid9KTtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGUoa2V5ICsgJ1sxXScsIHZhbFsxXSwgc3BlYyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZl8odmFsWzBdKSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzcGVjLmZ1bmN0aW9uID09PSAncGllY2V3aXNlLWNvbnN0YW50JyAmJiB2YWxbMF0gJSAxICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Ioa2V5ICsgJ1swXScsIHZhbFswXSwgJ3pvb20gbGV2ZWwgZm9yIHBpZWNld2lzZS1jb25zdGFudCBmdW5jdGlvbnMgbXVzdCBiZSBhbiBpbnRlZ2VyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxbMF0gPCBsYXN0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yKGtleSArICdbMF0nLCB2YWxbMF0sICdhcnJheSBzdG9wcyBtdXN0IGFwcGVhciBpbiBhc2NlbmRpbmcgb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFN0b3AgPSB2YWxbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2ZfKHZhbCkgPT09ICdhcnJheScgJiYgdmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2FycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgc3RvcCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhbGlkYXRlLmVudW0gPSBmdW5jdGlvbiAoa2V5LCB2YWwsIHNwZWMpIHtcbiAgICAgICAgaWYgKHNwZWMudmFsdWVzLmluZGV4T2YodW5idW5kbGUodmFsKSkgPT09IC0xKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2V4cGVjdGVkIG9uZSBvZiBbJXNdLCAlcyBmb3VuZCcsIHNwZWMudmFsdWVzLmpvaW4oJywgJyksIHZhbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFsaWRhdGUuY29sb3IgPSBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgaWYgKHR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBlcnJvcihrZXksIHZhbCwgJ2NvbG9yIGV4cGVjdGVkLCAlcyBmb3VuZCcsIHR5cGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcnNlQ1NTQ29sb3IodmFsKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICdjb2xvciBleHBlY3RlZCwgXCIlc1wiIGZvdW5kJywgdmFsKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB0eXBlVmFsaWRhdG9yKGV4cGVjdGVkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihrZXksIHZhbCwgc3BlYykge1xuICAgICAgICAgICAgdmFyIGFjdHVhbCA9IHR5cGVvZl8odmFsKTtcbiAgICAgICAgICAgIGlmIChhY3R1YWwgIT09IGV4cGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBleHBlY3RlZCwgJXMgZm91bmQnLCBleHBlY3RlZCwgYWN0dWFsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCdtaW5pbXVtJyBpbiBzcGVjICYmIHZhbCA8IHNwZWMubWluaW11bSkge1xuICAgICAgICAgICAgICAgIGVycm9yKGtleSwgdmFsLCAnJXMgaXMgbGVzcyB0aGFuIHRoZSBtaW5pbXVtIHZhbHVlICVzJywgdmFsLCBzcGVjLm1pbmltdW0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJ21heGltdW0nIGluIHNwZWMgJiYgdmFsID4gc3BlYy5tYXhpbXVtKSB7XG4gICAgICAgICAgICAgICAgZXJyb3Ioa2V5LCB2YWwsICclcyBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gdmFsdWUgJXMnLCB2YWwsIHNwZWMubWF4aW11bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFsaWRhdGUubnVtYmVyID0gdHlwZVZhbGlkYXRvcignbnVtYmVyJyk7XG4gICAgdmFsaWRhdGUuc3RyaW5nID0gdHlwZVZhbGlkYXRvcignc3RyaW5nJyk7XG4gICAgdmFsaWRhdGUuYm9vbGVhbiA9IHR5cGVWYWxpZGF0b3IoJ2Jvb2xlYW4nKTtcblxuICAgIHZhbGlkYXRlWycqJ10gPSBmdW5jdGlvbigpIHt9O1xuXG4gICAgdmFsaWRhdGUoJycsIHN0eWxlLCByZWZlcmVuY2UuJHJvb3QpO1xuXG4gICAgcmV0dXJuIGVycm9ycztcbn07XG5cbmZ1bmN0aW9uIHR5cGVvZl8odmFsKSB7XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE51bWJlcilcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBTdHJpbmcpXG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBpZiAodmFsIGluc3RhbmNlb2YgQm9vbGVhbilcbiAgICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICByZXR1cm4gJ2FycmF5JztcbiAgICBpZiAodmFsID09PSBudWxsKVxuICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgIHJldHVybiB0eXBlb2YgdmFsO1xufVxuXG5mdW5jdGlvbiB1bmJ1bmRsZShfKSB7XG4gICAgaWYgKF8gaW5zdGFuY2VvZiBOdW1iZXIgfHxcbiAgICAgICAgXyBpbnN0YW5jZW9mIFN0cmluZyB8fFxuICAgICAgICBfIGluc3RhbmNlb2YgQm9vbGVhbikge1xuICAgICAgICByZXR1cm4gXy52YWx1ZU9mKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIF87XG4gICAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3Y3Lmpzb24nKTtcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkdmVyc2lvblwiOiA3LFxuICBcIiRyb290XCI6IHtcbiAgICBcInZlcnNpb25cIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICA3XG4gICAgICBdLFxuICAgICAgXCJkb2NcIjogXCJTdHlsZXNoZWV0IHZlcnNpb24gbnVtYmVyLiBNdXN0IGJlIDcuXCJcbiAgICB9LFxuICAgIFwibmFtZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBodW1hbi1yZWFkYWJsZSBuYW1lIGZvciB0aGUgc3R5bGUuXCJcbiAgICB9LFxuICAgIFwiY29uc3RhbnRzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbnN0YW50c1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBvYmplY3Qgb2YgY29uc3RhbnRzIHRvIGJlIHJlZmVyZW5jZWQgaW4gbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZXNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwic291cmNlc1wiLFxuICAgICAgXCJkb2NcIjogXCJEYXRhIHNvdXJjZSBzcGVjaWZpY2F0aW9ucy5cIlxuICAgIH0sXG4gICAgXCJzcHJpdGVcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgYmFzZSBVUkwgZm9yIHJldHJpZXZpbmcgdGhlIHNwcml0ZSBpbWFnZSBhbmQgbWV0YWRhdGEuIFRoZSBleHRlbnNpb25zIGAucG5nYCwgYC5qc29uYCBhbmQgc2NhbGUgZmFjdG9yIGBAMngucG5nYCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQuXCJcbiAgICB9LFxuICAgIFwiZ2x5cGhzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJBIFVSTCB0ZW1wbGF0ZSBmb3IgbG9hZGluZyBzaWduZWQtZGlzdGFuY2UtZmllbGQgZ2x5cGggc2V0cyBpbiBQQkYgZm9ybWF0LiBWYWxpZCB0b2tlbnMgYXJlIHtmb250c3RhY2t9IGFuZCB7cmFuZ2V9LlwiXG4gICAgfSxcbiAgICBcInRyYW5zaXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwidHJhbnNpdGlvblwiLFxuICAgICAgXCJkb2NcIjogXCJBIGdsb2JhbCB0cmFuc2l0aW9uIGRlZmluaXRpb24gdG8gdXNlIGFzIGEgZGVmYXVsdCBhY3Jvc3MgcHJvcGVydGllcy5cIlxuICAgIH0sXG4gICAgXCJsYXllcnNcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgIFwidmFsdWVcIjogXCJsYXllclwiLFxuICAgICAgXCJkb2NcIjogXCJMYXllcnMgd2lsbCBiZSBkcmF3biBpbiB0aGUgb3JkZXIgb2YgdGhpcyBhcnJheS5cIlxuICAgIH1cbiAgfSxcbiAgXCJjb25zdGFudHNcIjoge1xuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIkEgY29uc3RhbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkIHZlcmJhdGltIGluIHRoZSByZWZlcmVuY2luZyBwbGFjZS4gVGhpcyBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBvYmplY3RzIGFuZCBhcnJheXMuIEFsbCB2YXJpYWJsZSBuYW1lcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggYW4gYEBgIHN5bWJvbC5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VzXCI6IHtcbiAgICBcIipcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic291cmNlXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmljYXRpb24gb2YgYSBkYXRhIHNvdXJjZS4gRm9yIHZlY3RvciBhbmQgcmFzdGVyIHNvdXJjZXMsIGVpdGhlciBUaWxlSlNPTiBvciBhIFVSTCB0byBhIFRpbGVKU09OIG11c3QgYmUgcHJvdmlkZWQuIEZvciBHZW9KU09OIGFuZCB2aWRlbyBzb3VyY2VzLCBhIFVSTCBtdXN0IGJlIHByb3ZpZGVkLlwiXG4gICAgfVxuICB9LFxuICBcInNvdXJjZVwiOiBbXG4gICAgXCJzb3VyY2VfdGlsZVwiLFxuICAgIFwic291cmNlX2dlb2pzb25cIixcbiAgICBcInNvdXJjZV92aWRlb1wiXG4gIF0sXG4gIFwic291cmNlX3RpbGVcIjoge1xuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmVjdG9yXCIsXG4gICAgICAgIFwicmFzdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlRoZSBkYXRhIHR5cGUgb2YgdGhlIHNvdXJjZS5cIlxuICAgIH0sXG4gICAgXCJ1cmxcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkEgVVJMIHRvIGEgVGlsZUpTT04gcmVzb3VyY2UuIFN1cHBvcnRlZCBwcm90b2NvbHMgYXJlIGBodHRwOmAsIGBodHRwczpgLCBhbmQgYG1hcGJveDovLzxtYXBpZD5gLlwiXG4gICAgfSxcbiAgICBcInRpbGVzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIkFuIGFycmF5IG9mIG9uZSBvciBtb3JlIHRpbGUgc291cmNlIFVSTHMsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSB6b29tIGxldmVsIGZvciB3aGljaCB0aWxlcyBhcmUgYXZhaWxhYmxlLCBhcyBpbiB0aGUgVGlsZUpTT04gc3BlYy5cIlxuICAgIH0sXG4gICAgXCJtYXh6b29tXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJNYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHdoaWNoIHRpbGVzIGFyZSBhdmFpbGFibGUsIGFzIGluIHRoZSBUaWxlSlNPTiBzcGVjLiBEYXRhIGZyb20gdGlsZXMgYXQgdGhlIG1heHpvb20gYXJlIHVzZWQgd2hlbiBkaXNwbGF5aW5nIHRoZSBtYXAgYXQgaGlnaGVyIHpvb20gbGV2ZWxzLlwiXG4gICAgfSxcbiAgICBcInRpbGVTaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDUxMixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gdmlzdWFsIHNpemUgdG8gZGlzcGxheSB0aWxlcyBmb3IgdGhpcyBsYXllci4gT25seSBjb25maWd1cmFibGUgZm9yIHJhc3RlciBsYXllcnMuXCJcbiAgICB9LFxuICAgIFwiKlwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCIsXG4gICAgICBcImRvY1wiOiBcIk90aGVyIGtleXMgdG8gY29uZmlndXJlIHRoZSBkYXRhIHNvdXJjZS5cIlxuICAgIH1cbiAgfSxcbiAgXCJzb3VyY2VfZ2VvanNvblwiOiB7XG4gICAgXCJ0eXBlXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJnZW9qc29uXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiZGF0YVwiOiB7XG4gICAgICBcInR5cGVcIjogXCIqXCJcbiAgICB9XG4gIH0sXG4gIFwic291cmNlX3ZpZGVvXCI6IHtcbiAgICBcInR5cGVcIjoge1xuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpZGVvXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidXJsXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImRvY1wiOiBcIlVSTHMgdG8gdmlkZW8gY29udGVudCBpbiBvcmRlciBvZiBwcmVmZXJyZWQgZm9ybWF0LlwiXG4gICAgfSxcbiAgICBcImNvb3JkaW5hdGVzXCI6IHtcbiAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcImxlbmd0aFwiOiA0LFxuICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIlxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgXCJsYXllclwiOiB7XG4gICAgXCJpZFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiVW5pcXVlIGxheWVyIG5hbWUuXCJcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiZmlsbFwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJzeW1ib2xcIixcbiAgICAgICAgXCJyYXN0ZXJcIixcbiAgICAgICAgXCJiYWNrZ3JvdW5kXCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIlJlbmRlcmluZyB0eXBlIG9mIHRoaXMgbGF5ZXIuXCJcbiAgICB9LFxuICAgIFwicmVmXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJkb2NcIjogXCJSZWZlcmVuY2VzIGFub3RoZXIgbGF5ZXIgdG8gY29weSBgdHlwZWAsIGBzb3VyY2VgLCBgc291cmNlLWxheWVyYCwgYG1pbnpvb21gLCBgbWF4em9vbWAsIGBmaWx0ZXJgLCBhbmQgYGxheW91dGAgcHJvcGVydGllcyBmcm9tLiBUaGlzIGFsbG93cyB0aGUgbGF5ZXJzIHRvIHNoYXJlIHByb2Nlc3NpbmcgYW5kIGJlIG1vcmUgZWZmaWNpZW50LlwiXG4gICAgfSxcbiAgICBcInNvdXJjZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTmFtZSBvZiBhIHNvdXJjZSBkZXNjcmlwdGlvbiB0byBiZSB1c2VkIGZvciB0aGlzIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInNvdXJjZS1sYXllclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZG9jXCI6IFwiTGF5ZXIgdG8gdXNlIGZyb20gYSB2ZWN0b3IgdGlsZSBzb3VyY2UuIFJlcXVpcmVkIGlmIHRoZSBzb3VyY2Ugc3VwcG9ydHMgbXVsdGlwbGUgbGF5ZXJzLlwiXG4gICAgfSxcbiAgICBcIm1pbnpvb21cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAyMixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbGF5ZXIgZ2V0cyBwYXJzZWQgYW5kIGFwcGVhcnMgb24uXCJcbiAgICB9LFxuICAgIFwibWF4em9vbVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgICAgXCJkb2NcIjogXCJUaGUgbWF4aW11bSB6b29tIGxldmVsIG9uIHdoaWNoIHRoZSBsYXllciBnZXRzIHBhcnNlZCBhbmQgYXBwZWFycyBvbi5cIlxuICAgIH0sXG4gICAgXCJpbnRlcmFjdGl2ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRvY1wiOiBcIkVuYWJsZSBxdWVyeWluZyBvZiBmZWF0dXJlIGRhdGEgZnJvbSB0aGlzIGxheWVyIGZvciBpbnRlcmFjdGl2aXR5LlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlXG4gICAgfSxcbiAgICBcImZpbHRlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJmaWx0ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiQSBleHByZXNzaW9uIHNwZWNpZnlpbmcgY29uZGl0aW9ucyBvbiBzb3VyY2UgZmVhdHVyZXMuIE9ubHkgZmVhdHVyZXMgdGhhdCBtYXRjaCB0aGUgZmlsdGVyIGFyZSBkaXNwbGF5ZWQuXCJcbiAgICB9LFxuICAgIFwibGF5b3V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImxheW91dFwiLFxuICAgICAgXCJkb2NcIjogXCJMYXlvdXQgcHJvcGVydGllcyBmb3IgdGhlIGxheWVyLlwiXG4gICAgfSxcbiAgICBcInBhaW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkRlZmF1bHQgcGFpbnQgcHJvcGVydGllcyBmb3IgdGhpcyBsYXllci5cIlxuICAgIH0sXG4gICAgXCJwYWludC4qXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInBhaW50XCIsXG4gICAgICBcImRvY1wiOiBcIkNsYXNzLXNwZWNpZmljIHBhaW50IHByb3BlcnRpZXMgZm9yIHRoaXMgbGF5ZXIuIFRoZSBjbGFzcyBuYW1lIGlzIHRoZSBwYXJ0IGFmdGVyIHRoZSBmaXJzdCBkb3QuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0XCI6IFtcbiAgICBcImxheW91dF9maWxsXCIsXG4gICAgXCJsYXlvdXRfbGluZVwiLFxuICAgIFwibGF5b3V0X3N5bWJvbFwiLFxuICAgIFwibGF5b3V0X3Jhc3RlclwiLFxuICAgIFwibGF5b3V0X2JhY2tncm91bmRcIlxuICBdLFxuICBcImxheW91dF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9maWxsXCI6IHtcbiAgICBcInZpc2liaWxpdHlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcInZpc2libGVcIixcbiAgICAgICAgXCJub25lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aXNpYmxlXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBkaXNwbGF5IG9mIHRoaXMgbGF5ZXIuIGBub25lYCBoaWRlcyB0aGlzIGxheWVyLlwiXG4gICAgfVxuICB9LFxuICBcImxheW91dF9saW5lXCI6IHtcbiAgICBcImxpbmUtY2FwXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJidXR0XCIsXG4gICAgICAgIFwicm91bmRcIixcbiAgICAgICAgXCJzcXVhcmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImJ1dHRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgbGluZSBlbmRpbmdzLlwiXG4gICAgfSxcbiAgICBcImxpbmUtam9pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwiYmV2ZWxcIixcbiAgICAgICAgXCJyb3VuZFwiLFxuICAgICAgICBcIm1pdGVyXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJtaXRlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiBsaW5lcyB3aGVuIGpvaW5pbmcuXCJcbiAgICB9LFxuICAgIFwibGluZS1taXRlci1saW1pdFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJVc2VkIHRvIGF1dG9tYXRpY2FsbHkgY29udmVydCBtaXRlciBqb2lucyB0byBiZXZlbCBqb2lucyBmb3Igc2hhcnAgYW5nbGVzLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcImxpbmUtam9pblwiOiBcIm1pdGVyXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXJvdW5kLWxpbWl0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlVzZWQgdG8gYXV0b21hdGljYWxseSBjb252ZXJ0IHJvdW5kIGpvaW5zIHRvIG1pdGVyIGpvaW5zIGZvciBzaGFsbG93IGFuZ2xlcy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJsaW5lLWpvaW5cIjogXCJyb3VuZFwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3N5bWJvbFwiOiB7XG4gICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgICBcInBvaW50XCIsXG4gICAgICAgICAgXCJsaW5lXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJwb2ludFwiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBwbGFjZW1lbnQgcmVsYXRpdmUgdG8gaXRzIGdlb21ldHJ5LiBgbGluZWAgY2FuIG9ubHkgYmUgdXNlZCBvbiBMaW5lU3RyaW5ncyBhbmQgUG9seWdvbnMuXCJcbiAgICB9LFxuICAgIFwic3ltYm9sLW1pbi1kaXN0YW5jZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAyNTAsXG4gICAgICBcIm1pbmltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiTWluaW11bSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzeW1ib2wgYW5jaG9ycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgXCJzeW1ib2wtcGxhY2VtZW50XCI6IFwibGluZVwiXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9LFxuICAgIFwic3ltYm9sLWF2b2lkLWVkZ2VzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZSxcbiAgICAgIFwiZG9jXCI6IFwiSWYgdHJ1ZSwgdGhlIHN5bWJvbHMgd2lsbCBub3QgY3Jvc3MgdGlsZSBlZGdlcyB0byBhdm9pZCBtdXR1YWwgY29sbGlzaW9ucy4gUmVjb21tZW5kZWQgaW4gbGF5ZXJzIHRoYXQgZG9uJ3QgaGF2ZSBlbm91Z2ggcGFkZGluZyBpbiB0aGUgdmVjdG9yIHRpbGUgdG8gcHJldmVudCBjb2xsaXNpb25zLCBvciBpZiBpdCBpcyBhIHBvaW50IHN5bWJvbCBsYXllciBwbGFjZWQgYWZ0ZXIgYSBsaW5lIHN5bWJvbCBsYXllci5cIlxuICAgIH0sXG4gICAgXCJpY29uLWFsbG93LW92ZXJsYXBcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiB3aWxsIGJlIHZpc2libGUgZXZlbiBpZiBpdCBjb2xsaWRlcyB3aXRoIG90aGVyIGljb25zIGFuZCB0ZXh0LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taWdub3JlLXBsYWNlbWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBpY29uIHdvbid0IGFmZmVjdCBwbGFjZW1lbnQgb2Ygb3RoZXIgaWNvbnMgYW5kIHRleHQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgaWNvbiwgaW4gc3BhY2VzIHdoZXJlIHRoZSBpY29uIHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIHdoZW4gbWFwIGlzIHJvdGF0ZWQuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1tYXgtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIGZhY3RvciB0byBzY2FsZSB0aGUgaWNvbi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkb2NcIjogXCJBIHN0cmluZyB3aXRoIHt0b2tlbnN9IHJlcGxhY2VkLCByZWZlcmVuY2luZyB0aGUgZGF0YSBwcm9wZXJ0eSB0byBwdWxsIGZyb20uXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlXG4gICAgfSxcbiAgICBcImljb24tcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSBpY29uIGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCBpY29uIGJvdW5kaW5nIGJveCB0byBhdm9pZCBpY29uIGNvbGxpc2lvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1rZWVwLXVwcmlnaHRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgaWNvbiBtYXkgYmUgZmxpcHBlZCB0byBwcmV2ZW50IGl0IGZyb20gYmVpbmcgcmVuZGVyZWQgdXBzaWRlLWRvd25cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAge1xuICAgICAgICAgIFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tb2Zmc2V0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSWNvbidzIG9mZnNldCBkaXN0YW5jZS4gVmFsdWVzIGFyZSBbeCwgeV0gd2hlcmUgbmVnYXRpdmVzIGluZGljYXRlIGxlZnQgYW5kIHVwLCByZXNwZWN0aXZlbHkuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJ2aWV3cG9ydFwiLFxuICAgICAgXCJkb2NcIjogXCJPcmllbnRhdGlvbiBvZiBpY29uIG9yIHRleHQgd2hlbiBtYXAgaXMgcm90YXRlZC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWZpZWxkXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiXCIsXG4gICAgICBcInRva2Vuc1wiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJWYWx1ZSB0byB1c2UgZm9yIGEgdGV4dCBsYWJlbC4gRmVhdHVyZSBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdG9rZW5zIGxpa2Uge2ZpZWxkX25hbWV9LlwiXG4gICAgfSxcbiAgICBcInRleHQtZm9udFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIk9wZW4gU2FucyBSZWd1bGFyLCBBcmlhbCBVbmljb2RlIE1TIFJlZ3VsYXJcIixcbiAgICAgIFwiZG9jXCI6IFwiRm9udCBzdGFjayB0byB1c2UgZm9yIGRpc3BsYXlpbmcgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE2LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBtYXhpbXVtIHNpemUgdGV4dCB3aWxsIGJlIGxhaWQgb3V0LCB0byBjYWxjdWxhdGUgY29sbGlzaW9ucyB3aXRoLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtbWF4LXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDE1LFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG1heGltdW0gbGluZSB3aWR0aCBmb3IgdGV4dCB3cmFwcGluZy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxpbmUtaGVpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEuMixcbiAgICAgIFwidW5pdHNcIjogXCJlbVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJUZXh0IGxlYWRpbmcgdmFsdWUgZm9yIG11bHRpLWxpbmUgdGV4dC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInVuaXRzXCI6IFwiZW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBrZXJuaW5nIHZhbHVlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtanVzdGlmeVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibGVmdFwiLFxuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcInJpZ2h0XCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJjZW50ZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGV4dCBqdXN0aWZpY2F0aW9uIG9wdGlvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcImNlbnRlclwiLFxuICAgICAgICBcImxlZnRcIixcbiAgICAgICAgXCJyaWdodFwiLFxuICAgICAgICBcInRvcFwiLFxuICAgICAgICBcImJvdHRvbVwiLFxuICAgICAgICBcInRvcC1sZWZ0XCIsXG4gICAgICAgIFwidG9wLXJpZ2h0XCIsXG4gICAgICAgIFwiYm90dG9tLWxlZnRcIixcbiAgICAgICAgXCJib3R0b20tcmlnaHRcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcImNlbnRlclwiLFxuICAgICAgXCJkb2NcIjogXCJXaGljaCBwYXJ0IG9mIHRoZSB0ZXh0IHRvIHBsYWNlIGNsb3Nlc3QgdG8gdGhlIGFuY2hvci5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW1heC1hbmdsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiA0NSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIk1heGltdW0gYW5nbGUgY2hhbmdlIGJldHdlZW4gYWRqYWNlbnQgY2hhcmFjdGVycy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwic3ltYm9sLXBsYWNlbWVudFwiOiBcImxpbmVcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcInVuaXRzXCI6IFwiZGVncmVlc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJSb3RhdGVzIHRoZSB0ZXh0IGNsb2Nrd2lzZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LXBhZGRpbmdcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJkb2NcIjogXCJQYWRkaW5nIHZhbHVlIGFyb3VuZCB0ZXh0IGJvdW5kaW5nIGJveCB0byBhdm9pZCBsYWJlbCBjb2xsaXNpb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQta2VlcC11cHJpZ2h0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCBtYXkgYmUgZmxpcHBlZCB2ZXJ0aWNhbGx5IHRvIHByZXZlbnQgaXQgZnJvbSBiZWluZyByZW5kZXJlZCB1cHNpZGUtZG93bi5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAge1xuICAgICAgICAgIFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjogXCJtYXBcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNmb3JtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJub25lXCIsXG4gICAgICAgIFwidXBwZXJjYXNlXCIsXG4gICAgICAgIFwibG93ZXJjYXNlXCJcbiAgICAgIF0sXG4gICAgICBcImRlZmF1bHRcIjogXCJub25lXCIsXG4gICAgICBcImRvY1wiOiBcIlNwZWNpZmllcyBob3cgdG8gY2FwaXRhbGl6ZSB0ZXh0LCBzaW1pbGFyIHRvIHRoZSBDU1MgYHRleHQtdHJhbnNmb3JtYCBwcm9wZXJ0eS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LW9mZnNldFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGRpc3RhbmNlIHRoYXQgdGV4dCBpcyBvZmZzZXQgZnJvbSBpdHMgYW5jaG9yIGhvcml6b250YWxseSBhbmQgdmVydGljYWxseS5cIixcbiAgICAgIFwidmFsdWVcIjogXCJudW1iZXJcIixcbiAgICAgIFwidW5pdHNcIjogXCJlbXNcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwibGVuZ3RoXCI6IDIsXG4gICAgICBcImRlZmF1bHRcIjogW1xuICAgICAgICAwLFxuICAgICAgICAwXG4gICAgICBdLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtYWxsb3ctb3ZlcmxhcFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSB0ZXh0IHdpbGwgYmUgdmlzaWJsZSBldmVuIGlmIGl0IGNvbGxpZGVzIHdpdGggb3RoZXIgaWNvbnMgYW5kIGxhYmVscy5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJkZWZhdWx0XCI6IGZhbHNlLFxuICAgICAgXCJkb2NcIjogXCJJZiB0cnVlLCB0aGUgdGV4dCB3b24ndCBhZmZlY3QgcGxhY2VtZW50IG9mIG90aGVyIGljb25zIGFuZCBsYWJlbHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1vcHRpb25hbFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2UsXG4gICAgICBcImRvY1wiOiBcIklmIHRydWUsIHRoZSBzeW1ib2wgd2lsbCBhcHBlYXIgd2l0aG91dCBpdHMgdGV4dCwgaW4gc3BhY2VzIHdoZXJlIHRoZSB0ZXh0IHdvdWxkIG1ha2UgaXQgdG9vIGxhcmdlIHRvIGZpdC5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcInRleHQtZmllbGRcIixcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidmlzaWJpbGl0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwidmlzaWJsZVwiLFxuICAgICAgICBcIm5vbmVcIlxuICAgICAgXSxcbiAgICAgIFwiZGVmYXVsdFwiOiBcInZpc2libGVcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGRpc3BsYXkgb2YgdGhpcyBsYXllci4gYG5vbmVgIGhpZGVzIHRoaXMgbGF5ZXIuXCJcbiAgICB9XG4gIH0sXG4gIFwibGF5b3V0X3Jhc3RlclwiOiB7XG4gICAgXCJ2aXNpYmlsaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImVudW1cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJwaWVjZXdpc2UtY29uc3RhbnRcIixcbiAgICAgIFwidmFsdWVzXCI6IFtcbiAgICAgICAgXCJ2aXNpYmxlXCIsXG4gICAgICAgIFwibm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJkZWZhdWx0XCI6IFwidmlzaWJsZVwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZGlzcGxheSBvZiB0aGlzIGxheWVyLiBgbm9uZWAgaGlkZXMgdGhpcyBsYXllci5cIlxuICAgIH1cbiAgfSxcbiAgXCJmaWx0ZXJcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJ2YWx1ZVwiOiBcIipcIlxuICB9LFxuICBcImZpbHRlcl9vcGVyYXRvclwiOiB7XG4gICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgIFwidmFsdWVzXCI6IFtcbiAgICAgIFwiPT1cIixcbiAgICAgIFwiIT1cIixcbiAgICAgIFwiPlwiLFxuICAgICAgXCI+PVwiLFxuICAgICAgXCI8XCIsXG4gICAgICBcIjw9XCIsXG4gICAgICBcImluXCIsXG4gICAgICBcIiFpblwiLFxuICAgICAgXCJhbGxcIixcbiAgICAgIFwiYW55XCIsXG4gICAgICBcIm5vbmVcIlxuICAgIF1cbiAgfSxcbiAgXCJnZW9tZXRyeV90eXBlXCI6IHtcbiAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgXCJQb2ludFwiLFxuICAgICAgXCJMaW5lU3RyaW5nXCIsXG4gICAgICBcIlBvbHlnb25cIlxuICAgIF1cbiAgfSxcbiAgXCJmdW5jdGlvblwiOiB7XG4gICAgXCJzdG9wc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgXCJkb2NcIjogXCJBbiBhcnJheSBvZiBzdG9wcy5cIixcbiAgICAgIFwidmFsdWVcIjogXCJmdW5jdGlvbl9zdG9wXCJcbiAgICB9LFxuICAgIFwiYmFzZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIlRoZSBleHBvbmVudGlhbCBiYXNlIG9mIHRoZSBpbnRlcnBvbGF0aW9uIGN1cnZlLiBJdCBjb250cm9scyB0aGUgcmF0ZSBhdCB3aGljaCB0aGUgcmVzdWx0IGluY3JlYXNlcy4gSGlnaGVyIHZhbHVlcyBtYWtlIHRoZSByZXN1bHQgaW5jcmVhc2UgbW9yZSB0b3dhcmRzIHRoZSBoaWdoIGVuZCBvZiB0aGUgcmFuZ2UuIFdpdGggYDFgIHRoZSBzdG9wcyBhcmUgaW50ZXJwb2xhdGVkIGxpbmVhcmx5LlwiXG4gICAgfVxuICB9LFxuICBcImZ1bmN0aW9uX3N0b3BcIjoge1xuICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgXCJtYXhpbXVtXCI6IDIyLFxuICAgIFwidmFsdWVcIjogW1xuICAgICAgXCJudW1iZXJcIixcbiAgICAgIFwiY29sb3JcIlxuICAgIF0sXG4gICAgXCJsZW5ndGhcIjogMixcbiAgICBcImRvY1wiOiBcIlpvb20gbGV2ZWwgYW5kIHZhbHVlIHBhaXIuXCJcbiAgfSxcbiAgXCJwYWludFwiOiBbXG4gICAgXCJwYWludF9maWxsXCIsXG4gICAgXCJwYWludF9saW5lXCIsXG4gICAgXCJwYWludF9zeW1ib2xcIixcbiAgICBcInBhaW50X3Jhc3RlclwiLFxuICAgIFwicGFpbnRfYmFja2dyb3VuZFwiXG4gIF0sXG4gIFwicGFpbnRfZmlsbFwiOiB7XG4gICAgXCJmaWxsLWFudGlhbGlhc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcImRlZmF1bHRcIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiV2hldGhlciBvciBub3QgdGhlIGZpbGwgc2hvdWxkIGJlIGFudGlhbGlhc2VkLlwiXG4gICAgfSxcbiAgICBcImZpbGwtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgZ2l2ZW4gdG8gdGhlIGZpbGwgY29sb3IuXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJmaWxsLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBjb2xvciBvZiB0aGUgZmlsbC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLW91dGxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG91dGxpbmUgY29sb3Igb2YgdGhlIGZpbGwuIE1hdGNoZXMgdGhlIHZhbHVlIG9mIGBmaWxsLWNvbG9yYCBpZiB1bnNwZWNpZmllZC5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJmaWxsLWltYWdlXCJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIFwiZmlsbC1hbnRpYWxpYXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgZ2VvbWV0cnkncyBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiXG4gICAgfSxcbiAgICBcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiZmlsbC10cmFuc2xhdGVcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJmaWxsLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBmaWxscy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9saW5lXCI6IHtcbiAgICBcImxpbmUtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcImxpbmUtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGxpbmUgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJsZW5ndGhcIjogMixcbiAgICAgIFwiZGVmYXVsdFwiOiBbXG4gICAgICAgIDAsXG4gICAgICAgIDBcbiAgICAgIF0sXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGdlb21ldHJ5J3Mgb2Zmc2V0LiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIlxuICAgIH0sXG4gICAgXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImxpbmUtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwibGluZS13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiU3Ryb2tlIHRoaWNrbmVzcy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWdhcC13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImRvY1wiOiBcIkRyYXdzIGEgbGluZSBjYXNpbmcgb3V0c2lkZSBvZiBhIGxpbmUncyBhY3R1YWwgcGF0aC4gVmFsdWUgaW5kaWNhdGVzIHRoZSB3aWR0aCBvZiB0aGUgaW5uZXIgZ2FwLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCJcbiAgICB9LFxuICAgIFwibGluZS1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJCbHVyIGFwcGxpZWQgdG8gdGhlIGxpbmUsIGluIHBpeGVscy5cIlxuICAgIH0sXG4gICAgXCJsaW5lLWRhc2hhcnJheVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJTcGVjaWZpZXMgdGhlIGxlbmd0aHMgb2YgdGhlIGFsdGVybmF0aW5nIGRhc2hlcyBhbmQgZ2FwcyB0aGF0IGZvcm0gdGhlIGRhc2ggcGF0dGVybi4gVGhlIGxlbmd0aHMgYXJlIGxhdGVyIHNjYWxlZCBieSB0aGUgbGluZSB3aWR0aC4gVG8gY29udmVydCBhIGRhc2ggbGVuZ3RoIHRvIHBpeGVscywgbXVsdGlwbHkgdGhlIGxlbmd0aCBieSB0aGUgY3VycmVudCBsaW5lIHdpZHRoLlwiLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJsaW5lIHdpZHRoc1wiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJsaW5lLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJsaW5lLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk5hbWUgb2YgaW1hZ2UgaW4gc3ByaXRlIHRvIHVzZSBmb3IgZHJhd2luZyBpbWFnZSBsaW5lcy5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9zeW1ib2xcIjoge1xuICAgIFwiaWNvbi1vcGFjaXR5XCI6IHtcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIGljb24gd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1zaXplXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiU2NhbGUgZmFjdG9yIGZvciBpY29uLiAxIGlzIG9yaWdpbmFsIHNpemUsIDMgdHJpcGxlcyB0aGUgc2l6ZS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCIjMDAwMDAwXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uLiBUaGlzIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBzZGYgaWNvbnMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJpY29uLWltYWdlXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwiaWNvbi1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSBpY29uJ3MgaGFsby4gSWNvbiBoYWxvcyBjYW4gb25seSBiZSB1c2VkIHdpdGggc2RmIGljb25zLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby13aWR0aFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJwaXhlbHNcIixcbiAgICAgIFwiZG9jXCI6IFwiRGlzdGFuY2Ugb2YgaGFsbyB0byB0aGUgaWNvbiBvdXRsaW5lLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24taGFsby1ibHVyXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIG91dCB0aGUgaGFsbyB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwiaWNvbi1pbWFnZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcImljb24tdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJBbiBpY29uJ3Mgb2Zmc2V0IGRpc3RhbmNlLiBWYWx1ZXMgYXJlIFt4LCB5XSB3aGVyZSBuZWdhdGl2ZXMgaW5kaWNhdGUgbGVmdCBhbmQgdXAsIHJlc3BlY3RpdmVseS5cIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIlxuICAgICAgXVxuICAgIH0sXG4gICAgXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiZW51bVwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ2YWx1ZXNcIjogW1xuICAgICAgICBcIm1hcFwiLFxuICAgICAgICBcInZpZXdwb3J0XCJcbiAgICAgIF0sXG4gICAgICBcImRvY1wiOiBcIkNvbnRyb2wgd2hldGhlciB0aGUgdHJhbnNsYXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIG1hcCAobm9ydGgpIG9yIHZpZXdwb3J0IChzY3JlZW4pXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJtYXBcIixcbiAgICAgIFwicmVxdWlyZXNcIjogW1xuICAgICAgICBcImljb24taW1hZ2VcIixcbiAgICAgICAgXCJpY29uLXRyYW5zbGF0ZVwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtb3BhY2l0eVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIG9wYWNpdHkgYXQgd2hpY2ggdGhlIHRleHQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtc2l6ZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxNixcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIkZvbnQgc2l6ZS4gSWYgdW5zcGVjaWZpZWQsIHRoZSB0ZXh0IHdpbGwgYmUgYXMgYmlnIGFzIGFsbG93ZWQgYnkgdGhlIGxheWVyIGRlZmluaXRpb24uXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1jb2xvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJjb2xvclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgY29sb3Igd2l0aCB3aGljaCB0aGUgdGV4dCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IFwiIzAwMDAwMFwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWNvbG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImNvbG9yXCIsXG4gICAgICBcImRlZmF1bHRcIjogXCJyZ2JhKDAsIDAsIDAsIDApXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIG9mIHRoZSB0ZXh0J3MgaGFsbywgd2hpY2ggaGVscHMgaXQgc3RhbmQgb3V0IGZyb20gYmFja2dyb3VuZHMuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLXdpZHRoXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJEaXN0YW5jZSBvZiBoYWxvIHRvIHRoZSBmb250IG91dGxpbmUuIE1heCB0ZXh0IGhhbG8gd2lkdGggaXMgMS80IG9mIHRoZSBmb250LXNpemUuXCIsXG4gICAgICBcInJlcXVpcmVzXCI6IFtcbiAgICAgICAgXCJ0ZXh0LWZpZWxkXCJcbiAgICAgIF1cbiAgICB9LFxuICAgIFwidGV4dC1oYWxvLWJsdXJcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcInVuaXRzXCI6IFwicGl4ZWxzXCIsXG4gICAgICBcImRvY1wiOiBcIlRoZSBoYWxvJ3MgZmFkZW91dCBkaXN0YW5jZSB0b3dhcmRzIHRoZSBvdXRzaWRlLlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcInZhbHVlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImxlbmd0aFwiOiAyLFxuICAgICAgXCJkZWZhdWx0XCI6IFtcbiAgICAgICAgMCxcbiAgICAgICAgMFxuICAgICAgXSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcInBpeGVsc1wiLFxuICAgICAgXCJkb2NcIjogXCJMYWJlbCBvZmZzZXQuIFZhbHVlcyBhcmUgW3gsIHldIHdoZXJlIG5lZ2F0aXZlcyBpbmRpY2F0ZSBsZWZ0IGFuZCB1cCwgcmVzcGVjdGl2ZWx5LlwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBcInRleHQtdHJhbnNsYXRlLWFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJlbnVtXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwicGllY2V3aXNlLWNvbnN0YW50XCIsXG4gICAgICBcInZhbHVlc1wiOiBbXG4gICAgICAgIFwibWFwXCIsXG4gICAgICAgIFwidmlld3BvcnRcIlxuICAgICAgXSxcbiAgICAgIFwiZG9jXCI6IFwiQ29udHJvbCB3aGV0aGVyIHRoZSB0cmFuc2xhdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgbWFwIChub3J0aCkgb3Igdmlld3BvcnQgKHNjcmVlbilcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIm1hcFwiLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIFwidGV4dC1maWVsZFwiLFxuICAgICAgICBcInRleHQtdHJhbnNsYXRlXCJcbiAgICAgIF1cbiAgICB9XG4gIH0sXG4gIFwicGFpbnRfcmFzdGVyXCI6IHtcbiAgICBcInJhc3Rlci1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgaW1hZ2Ugd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxLFxuICAgICAgXCJtaW5pbXVtXCI6IDAsXG4gICAgICBcIm1heGltdW1cIjogMSxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlXG4gICAgfSxcbiAgICBcInJhc3Rlci1odWUtcm90YXRlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDAsXG4gICAgICBcInBlcmlvZFwiOiAzNjAsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZSxcbiAgICAgIFwidW5pdHNcIjogXCJkZWdyZWVzXCIsXG4gICAgICBcImRvY1wiOiBcIlJvdGF0ZXMgaHVlcyBhcm91bmQgdGhlIGNvbG9yIHdoZWVsLlwiXG4gICAgfSxcbiAgICBcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwiZG9jXCI6IFwiSW5jcmVhc2Ugb3IgcmVkdWNlIHRoZSBicmlnaHRuZXNzIG9mIHRoZSBpbWFnZS4gVGhlIHZhbHVlIGlzIHRoZSBtaW5pbXVtIGJyaWdodG5lc3MuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgYnJpZ2h0bmVzcyBvZiB0aGUgaW1hZ2UuIFRoZSB2YWx1ZSBpcyB0aGUgbWF4aW11bSBicmlnaHRuZXNzLlwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLXNhdHVyYXRpb25cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRvY1wiOiBcIkluY3JlYXNlIG9yIHJlZHVjZSB0aGUgc2F0dXJhdGlvbiBvZiB0aGUgaW1hZ2UuXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAtMSxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9LFxuICAgIFwicmFzdGVyLWNvbnRyYXN0XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkb2NcIjogXCJJbmNyZWFzZSBvciByZWR1Y2UgdGhlIGNvbnRyYXN0IG9mIHRoZSBpbWFnZS5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiAwLFxuICAgICAgXCJtaW5pbXVtXCI6IC0xLFxuICAgICAgXCJtYXhpbXVtXCI6IDEsXG4gICAgICBcImZ1bmN0aW9uXCI6IFwiaW50ZXJwb2xhdGVkXCIsXG4gICAgICBcInRyYW5zaXRpb25cIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJGYWRlIGR1cmF0aW9uIHdoZW4gYSBuZXcgdGlsZSBpcyBhZGRlZC5cIlxuICAgIH1cbiAgfSxcbiAgXCJwYWludF9iYWNrZ3JvdW5kXCI6IHtcbiAgICBcImJhY2tncm91bmQtY29sb3JcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwiY29sb3JcIixcbiAgICAgIFwiZGVmYXVsdFwiOiBcIiMwMDAwMDBcIixcbiAgICAgIFwiZG9jXCI6IFwiVGhlIGNvbG9yIHdpdGggd2hpY2ggdGhlIGJhY2tncm91bmQgd2lsbCBiZSBkcmF3bi5cIixcbiAgICAgIFwiZnVuY3Rpb25cIjogXCJpbnRlcnBvbGF0ZWRcIixcbiAgICAgIFwidHJhbnNpdGlvblwiOiB0cnVlLFxuICAgICAgXCJyZXF1aXJlc1wiOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBcIiFcIjogXCJiYWNrZ3JvdW5kLWltYWdlXCJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG4gICAgXCJiYWNrZ3JvdW5kLWltYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcInBpZWNld2lzZS1jb25zdGFudFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWUsXG4gICAgICBcImRvY1wiOiBcIk9wdGlvbmFsbHkgYW4gaW1hZ2Ugd2hpY2ggaXMgZHJhd24gYXMgdGhlIGJhY2tncm91bmQuXCJcbiAgICB9LFxuICAgIFwiYmFja2dyb3VuZC1vcGFjaXR5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDEsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwibWF4aW11bVwiOiAxLFxuICAgICAgXCJkb2NcIjogXCJUaGUgb3BhY2l0eSBhdCB3aGljaCB0aGUgYmFja2dyb3VuZCB3aWxsIGJlIGRyYXduLlwiLFxuICAgICAgXCJmdW5jdGlvblwiOiBcImludGVycG9sYXRlZFwiLFxuICAgICAgXCJ0cmFuc2l0aW9uXCI6IHRydWVcbiAgICB9XG4gIH0sXG4gIFwidHJhbnNpdGlvblwiOiB7XG4gICAgXCJkdXJhdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAzMDAsXG4gICAgICBcIm1pbmltdW1cIjogMCxcbiAgICAgIFwidW5pdHNcIjogXCJtaWxsaXNlY29uZHNcIixcbiAgICAgIFwiZG9jXCI6IFwiVGltZSBhbGxvdHRlZCBmb3IgdHJhbnNpdGlvbnMgdG8gY29tcGxldGUuXCJcbiAgICB9LFxuICAgIFwiZGVsYXlcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCIsXG4gICAgICBcImRlZmF1bHRcIjogMCxcbiAgICAgIFwibWluaW11bVwiOiAwLFxuICAgICAgXCJ1bml0c1wiOiBcIm1pbGxpc2Vjb25kc1wiLFxuICAgICAgXCJkb2NcIjogXCJMZW5ndGggb2YgdGltZSBiZWZvcmUgYSB0cmFuc2l0aW9uIGJlZ2lucy5cIlxuICAgIH1cbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBsaWdodHdlaWdodCBCdWZmZXIgc2hpbSBmb3IgcGJmIGJyb3dzZXIgYnVpbGRcbi8vIGJhc2VkIG9uIGNvZGUgZnJvbSBnaXRodWIuY29tL2Zlcm9zcy9idWZmZXIgKE1JVC1saWNlbnNlZClcblxubW9kdWxlLmV4cG9ydHMgPSBCdWZmZXI7XG5cbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpO1xuXG52YXIgQnVmZmVyTWV0aG9kcztcblxuZnVuY3Rpb24gQnVmZmVyKGxlbmd0aCkge1xuICAgIHZhciBhcnI7XG4gICAgaWYgKGxlbmd0aCAmJiBsZW5ndGgubGVuZ3RoKSB7XG4gICAgICAgIGFyciA9IGxlbmd0aDtcbiAgICAgICAgbGVuZ3RoID0gYXJyLmxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCB8fCAwKTtcbiAgICBpZiAoYXJyKSBidWYuc2V0KGFycik7XG5cbiAgICBidWYucmVhZFVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkVUludDMyTEU7XG4gICAgYnVmLndyaXRlVUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG4gICAgYnVmLnJlYWRJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy5yZWFkSW50MzJMRTtcbiAgICBidWYud3JpdGVJbnQzMkxFID0gQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEU7XG4gICAgYnVmLnJlYWRGbG9hdExFID0gQnVmZmVyTWV0aG9kcy5yZWFkRmxvYXRMRTtcbiAgICBidWYud3JpdGVGbG9hdExFID0gQnVmZmVyTWV0aG9kcy53cml0ZUZsb2F0TEU7XG4gICAgYnVmLnJlYWREb3VibGVMRSA9IEJ1ZmZlck1ldGhvZHMucmVhZERvdWJsZUxFO1xuICAgIGJ1Zi53cml0ZURvdWJsZUxFID0gQnVmZmVyTWV0aG9kcy53cml0ZURvdWJsZUxFO1xuICAgIGJ1Zi50b1N0cmluZyA9IEJ1ZmZlck1ldGhvZHMudG9TdHJpbmc7XG4gICAgYnVmLndyaXRlID0gQnVmZmVyTWV0aG9kcy53cml0ZTtcbiAgICBidWYuc2xpY2UgPSBCdWZmZXJNZXRob2RzLnNsaWNlO1xuICAgIGJ1Zi5jb3B5ID0gQnVmZmVyTWV0aG9kcy5jb3B5O1xuXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWU7XG4gICAgcmV0dXJuIGJ1Zjtcbn1cblxudmFyIGxhc3RTdHIsIGxhc3RTdHJFbmNvZGVkO1xuXG5CdWZmZXJNZXRob2RzID0ge1xuICAgIHJlYWRVSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSAqIDB4MTAwMDAwMCk7XG4gICAgfSxcblxuICAgIHdyaXRlVUludDMyTEU6IGZ1bmN0aW9uKHZhbCwgcG9zKSB7XG4gICAgICAgIHRoaXNbcG9zXSA9IHZhbDtcbiAgICAgICAgdGhpc1twb3MgKyAxXSA9ICh2YWwgPj4+IDgpO1xuICAgICAgICB0aGlzW3BvcyArIDJdID0gKHZhbCA+Pj4gMTYpO1xuICAgICAgICB0aGlzW3BvcyArIDNdID0gKHZhbCA+Pj4gMjQpO1xuICAgIH0sXG5cbiAgICByZWFkSW50MzJMRTogZnVuY3Rpb24ocG9zKSB7XG4gICAgICAgIHJldHVybiAoKHRoaXNbcG9zXSkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMV0gPDwgOCkgfFxuICAgICAgICAgICAgKHRoaXNbcG9zICsgMl0gPDwgMTYpKSArXG4gICAgICAgICAgICAodGhpc1twb3MgKyAzXSA8PCAyNCk7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdExFOiAgZnVuY3Rpb24ocG9zKSB7IHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgcmVhZERvdWJsZUxFOiBmdW5jdGlvbihwb3MpIHsgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHdyaXRlRmxvYXRMRTogIGZ1bmN0aW9uKHZhbCwgcG9zKSB7IHJldHVybiBpZWVlNzU0LndyaXRlKHRoaXMsIHZhbCwgcG9zLCB0cnVlLCAyMywgNCk7IH0sXG4gICAgd3JpdGVEb3VibGVMRTogZnVuY3Rpb24odmFsLCBwb3MpIHsgcmV0dXJuIGllZWU3NTQud3JpdGUodGhpcywgdmFsLCBwb3MsIHRydWUsIDUyLCA4KTsgfSxcblxuICAgIHRvU3RyaW5nOiBmdW5jdGlvbihlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICAgICAgICB2YXIgc3RyID0gJycsXG4gICAgICAgICAgICB0bXAgPSAnJztcblxuICAgICAgICBzdGFydCA9IHN0YXJ0IHx8IDA7XG4gICAgICAgIGVuZCA9IE1hdGgubWluKHRoaXMubGVuZ3RoLCBlbmQgfHwgdGhpcy5sZW5ndGgpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2ggPSB0aGlzW2ldO1xuICAgICAgICAgICAgaWYgKGNoIDw9IDB4N0YpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gZGVjb2RlVVJJQ29tcG9uZW50KHRtcCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTtcbiAgICAgICAgICAgICAgICB0bXAgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdG1wICs9ICclJyArIGNoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN0ciArPSBkZWNvZGVVUklDb21wb25lbnQodG1wKTtcblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICB3cml0ZTogZnVuY3Rpb24oc3RyLCBwb3MpIHtcbiAgICAgICAgdmFyIGJ5dGVzID0gc3RyID09PSBsYXN0U3RyID8gbGFzdFN0ckVuY29kZWQgOiBlbmNvZGVTdHJpbmcoc3RyKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpc1twb3MgKyBpXSA9IGJ5dGVzW2ldO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNsaWNlOiBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpO1xuICAgIH0sXG5cbiAgICBjb3B5OiBmdW5jdGlvbihidWYsIHBvcykge1xuICAgICAgICBwb3MgPSBwb3MgfHwgMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBidWZbcG9zICsgaV0gPSB0aGlzW2ldO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuQnVmZmVyTWV0aG9kcy53cml0ZUludDMyTEUgPSBCdWZmZXJNZXRob2RzLndyaXRlVUludDMyTEU7XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgbGFzdFN0ciA9IHN0cjtcbiAgICBsYXN0U3RyRW5jb2RlZCA9IGVuY29kZVN0cmluZyhzdHIpO1xuICAgIHJldHVybiBsYXN0U3RyRW5jb2RlZC5sZW5ndGg7XG59O1xuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbihidWYpIHtcbiAgICByZXR1cm4gISEoYnVmICYmIGJ1Zi5faXNCdWZmZXIpO1xufTtcblxuZnVuY3Rpb24gZW5jb2RlU3RyaW5nKHN0cikge1xuICAgIHZhciBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICBieXRlcyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGMsIGxlYWQ7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSk7IC8vIGNvZGUgcG9pbnRcblxuICAgICAgICBpZiAoYyA+IDB4RDdGRiAmJiBjIDwgMHhFMDAwKSB7XG5cbiAgICAgICAgICAgIGlmIChsZWFkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGMgPCAweERDMDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IGM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYyA9IGxlYWQgLSAweEQ4MDAgPDwgMTAgfCBjIC0gMHhEQzAwIHwgMHgxMDAwMDtcbiAgICAgICAgICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjID4gMHhEQkZGIHx8IChpICsgMSA9PT0gbGVuZ3RoKSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKTtcbiAgICAgICAgICAgICAgICBlbHNlIGxlYWQgPSBjO1xuXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmIChsZWFkKSB7XG4gICAgICAgICAgICBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpO1xuICAgICAgICAgICAgbGVhZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODApIGJ5dGVzLnB1c2goYyk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDgwMCkgYnl0ZXMucHVzaChjID4+IDB4NiB8IDB4QzAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgICAgIGVsc2UgaWYgKGMgPCAweDEwMDAwKSBieXRlcy5wdXNoKGMgPj4gMHhDIHwgMHhFMCwgYyA+PiAweDYgJiAweDNGIHwgMHg4MCwgYyAmIDB4M0YgfCAweDgwKTtcbiAgICAgICAgZWxzZSBieXRlcy5wdXNoKGMgPj4gMHgxMiB8IDB4RjAsIGMgPj4gMHhDICYgMHgzRiB8IDB4ODAsIGMgPj4gMHg2ICYgMHgzRiB8IDB4ODAsIGMgJiAweDNGIHwgMHg4MCk7XG4gICAgfVxuICAgIHJldHVybiBieXRlcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBQYmY7XG5cbnZhciBCdWZmZXIgPSBnbG9iYWwuQnVmZmVyIHx8IHJlcXVpcmUoJy4vYnVmZmVyJyk7XG5cbmZ1bmN0aW9uIFBiZihidWYpIHtcbiAgICB0aGlzLmJ1ZiA9ICFCdWZmZXIuaXNCdWZmZXIoYnVmKSA/IG5ldyBCdWZmZXIoYnVmIHx8IDApIDogYnVmO1xuICAgIHRoaXMucG9zID0gMDtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMuYnVmLmxlbmd0aDtcbn1cblxuUGJmLlZhcmludCAgPSAwOyAvLyB2YXJpbnQ6IGludDMyLCBpbnQ2NCwgdWludDMyLCB1aW50NjQsIHNpbnQzMiwgc2ludDY0LCBib29sLCBlbnVtXG5QYmYuRml4ZWQ2NCA9IDE7IC8vIDY0LWJpdDogZG91YmxlLCBmaXhlZDY0LCBzZml4ZWQ2NFxuUGJmLkJ5dGVzICAgPSAyOyAvLyBsZW5ndGgtZGVsaW1pdGVkOiBzdHJpbmcsIGJ5dGVzLCBlbWJlZGRlZCBtZXNzYWdlcywgcGFja2VkIHJlcGVhdGVkIGZpZWxkc1xuUGJmLkZpeGVkMzIgPSA1OyAvLyAzMi1iaXQ6IGZsb2F0LCBmaXhlZDMyLCBzZml4ZWQzMlxuXG52YXIgU0hJRlRfTEVGVF8zMiA9ICgxIDw8IDE2KSAqICgxIDw8IDE2KSxcbiAgICBTSElGVF9SSUdIVF8zMiA9IDEgLyBTSElGVF9MRUZUXzMyLFxuICAgIFBPV18yXzYzID0gTWF0aC5wb3coMiwgNjMpO1xuXG5QYmYucHJvdG90eXBlID0ge1xuXG4gICAgZGVzdHJveTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuYnVmID0gbnVsbDtcbiAgICB9LFxuXG4gICAgLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHJlYWRGaWVsZHM6IGZ1bmN0aW9uKHJlYWRGaWVsZCwgcmVzdWx0LCBlbmQpIHtcbiAgICAgICAgZW5kID0gZW5kIHx8IHRoaXMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludCgpLFxuICAgICAgICAgICAgICAgIHRhZyA9IHZhbCA+PiAzLFxuICAgICAgICAgICAgICAgIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG5cbiAgICAgICAgICAgIHJlYWRGaWVsZCh0YWcsIHJlc3VsdCwgdGhpcyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gc3RhcnRQb3MpIHRoaXMuc2tpcCh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIHJlYWRNZXNzYWdlOiBmdW5jdGlvbihyZWFkRmllbGQsIHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkRmllbGRzKHJlYWRGaWVsZCwgcmVzdWx0LCB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zKTtcbiAgICB9LFxuXG4gICAgcmVhZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZFVJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFNGaXhlZDMyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRJbnQzMkxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgLy8gNjQtYml0IGludCBoYW5kbGluZyBpcyBiYXNlZCBvbiBnaXRodWIuY29tL2Rwdy9ub2RlLWJ1ZmZlci1tb3JlLWludHMgKE1JVC1saWNlbnNlZClcblxuICAgIHJlYWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMuYnVmLnJlYWRVSW50MzJMRSh0aGlzLnBvcykgKyB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRTRml4ZWQ2NDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkVUludDMyTEUodGhpcy5wb3MpICsgdGhpcy5idWYucmVhZEludDMyTEUodGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgICAgIHRoaXMucG9zICs9IDg7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWwgPSB0aGlzLmJ1Zi5yZWFkRmxvYXRMRSh0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSxcblxuICAgIHJlYWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsID0gdGhpcy5idWYucmVhZERvdWJsZUxFKHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBidWYgPSB0aGlzLmJ1ZixcbiAgICAgICAgICAgIHZhbCwgYiwgYjAsIGIxLCBiMiwgYjM7XG5cbiAgICAgICAgYjAgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMCA8IDB4ODApIHJldHVybiBiMDsgICAgICAgICAgICAgICAgIGIwID0gYjAgJiAweDdmO1xuICAgICAgICBiMSA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIxIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgPDwgNzsgICAgICAgYjEgPSAoYjEgJiAweDdmKSA8PCA3O1xuICAgICAgICBiMiA9IGJ1Zlt0aGlzLnBvcysrXTsgaWYgKGIyIDwgMHg4MCkgcmV0dXJuIGIwIHwgYjEgfCBiMiA8PCAxNDsgYjIgPSAoYjIgJiAweDdmKSA8PCAxNDtcbiAgICAgICAgYjMgPSBidWZbdGhpcy5wb3MrK107IGlmIChiMyA8IDB4ODApIHJldHVybiBiMCB8IGIxIHwgYjIgfCBiMyA8PCAyMTtcblxuICAgICAgICB2YWwgPSBiMCB8IGIxIHwgYjIgfCAoYjMgJiAweDdmKSA8PCAyMTtcblxuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDA7ICAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwOyAgICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4NDAwMDAwMDAwMDA7ICAgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MjAwMDAwMDAwMDAwMDsgICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4MTAwMDAwMDAwMDAwMDAwOyAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgICAgICBiID0gYnVmW3RoaXMucG9zKytdOyB2YWwgKz0gKGIgJiAweDdmKSAqIDB4ODAwMDAwMDAwMDAwMDAwMDsgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgdmFyaW50IG5vdCBtb3JlIHRoYW4gMTAgYnl0ZXMnKTtcbiAgICB9LFxuXG4gICAgcmVhZFZhcmludDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3MsXG4gICAgICAgICAgICB2YWwgPSB0aGlzLnJlYWRWYXJpbnQoKTtcblxuICAgICAgICBpZiAodmFsIDwgUE9XXzJfNjMpIHJldHVybiB2YWw7XG5cbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zIC0gMjtcbiAgICAgICAgd2hpbGUgKHRoaXMuYnVmW3Bvc10gPT09IDB4ZmYpIHBvcy0tO1xuICAgICAgICBpZiAocG9zIDwgc3RhcnRQb3MpIHBvcyA9IHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhbCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zIC0gc3RhcnRQb3MgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBiID0gfnRoaXMuYnVmW3N0YXJ0UG9zICsgaV0gJiAweDdmO1xuICAgICAgICAgICAgdmFsICs9IGkgPCA0ID8gYiA8PCBpICogNyA6IGIgKiBNYXRoLnBvdygyLCBpICogNyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLXZhbCAtIDE7XG4gICAgfSxcblxuICAgIHJlYWRTVmFyaW50OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG51bSA9IHRoaXMucmVhZFZhcmludCgpO1xuICAgICAgICByZXR1cm4gbnVtICUgMiA9PT0gMSA/IChudW0gKyAxKSAvIC0yIDogbnVtIC8gMjsgLy8gemlnemFnIGVuY29kaW5nXG4gICAgfSxcblxuICAgIHJlYWRCb29sZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpO1xuICAgIH0sXG5cbiAgICByZWFkU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBzdHIgPSB0aGlzLmJ1Zi50b1N0cmluZygndXRmOCcsIHRoaXMucG9zLCBlbmQpO1xuICAgICAgICB0aGlzLnBvcyA9IGVuZDtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuXG4gICAgcmVhZEJ5dGVzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsXG4gICAgICAgICAgICBidWZmZXIgPSB0aGlzLmJ1Zi5zbGljZSh0aGlzLnBvcywgZW5kKTtcbiAgICAgICAgdGhpcy5wb3MgPSBlbmQ7XG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfSxcblxuICAgIC8vIHZlcmJvc2UgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnM7IGRvZXNuJ3QgYWZmZWN0IGd6aXBwZWQgc2l6ZVxuXG4gICAgcmVhZFBhY2tlZFZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRWYXJpbnQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU1ZhcmludDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEJvb2xlYW46IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkQm9vbGVhbigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGbG9hdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRGbG9hdCgpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWREb3VibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRG91YmxlKCkpO1xuICAgICAgICByZXR1cm4gYXJyO1xuICAgIH0sXG4gICAgcmVhZFBhY2tlZEZpeGVkMzI6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLCBhcnIgPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSBhcnIucHVzaCh0aGlzLnJlYWRTRml4ZWQzMigpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9LFxuICAgIHJlYWRQYWNrZWRGaXhlZDY0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3MsIGFyciA9IFtdO1xuICAgICAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcbiAgICByZWFkUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZW5kID0gdGhpcy5yZWFkVmFyaW50KCkgKyB0aGlzLnBvcywgYXJyID0gW107XG4gICAgICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfSxcblxuICAgIHNraXA6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YXIgdHlwZSA9IHZhbCAmIDB4NztcbiAgICAgICAgaWYgKHR5cGUgPT09IFBiZi5WYXJpbnQpIHdoaWxlICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA+IDB4N2YpIHt9XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT09IFBiZi5CeXRlcykgdGhpcy5wb3MgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zO1xuICAgICAgICBlbHNlIGlmICh0eXBlID09PSBQYmYuRml4ZWQzMikgdGhpcy5wb3MgKz0gNDtcbiAgICAgICAgZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkNjQpIHRoaXMucG9zICs9IDg7XG4gICAgICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdVbmltcGxlbWVudGVkIHR5cGU6ICcgKyB0eXBlKTtcbiAgICB9LFxuXG4gICAgLy8gPT09IFdSSVRJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHdyaXRlVGFnOiBmdW5jdGlvbih0YWcsIHR5cGUpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludCgodGFnIDw8IDMpIHwgdHlwZSk7XG4gICAgfSxcblxuICAgIHJlYWxsb2M6IGZ1bmN0aW9uKG1pbikge1xuICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfHwgMTY7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aCA8IHRoaXMucG9zICsgbWluKSBsZW5ndGggKj0gMjtcblxuICAgICAgICBpZiAobGVuZ3RoICE9PSB0aGlzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKTtcbiAgICAgICAgICAgIHRoaXMuYnVmLmNvcHkoYnVmKTtcbiAgICAgICAgICAgIHRoaXMuYnVmID0gYnVmO1xuICAgICAgICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgZmluaXNoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLnBvcztcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcy5idWYuc2xpY2UoMCwgdGhpcy5sZW5ndGgpO1xuICAgIH0sXG5cbiAgICB3cml0ZUZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlVUludDMyTEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlU0ZpeGVkMzI6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRSh2YWwsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gNDtcbiAgICB9LFxuXG4gICAgd3JpdGVGaXhlZDY0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUludDMyTEUodmFsICYgLTEsIHRoaXMucG9zKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVVSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVTRml4ZWQ2NDogZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICAgICAgdGhpcy5idWYud3JpdGVJbnQzMkxFKHZhbCAmIC0xLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMuYnVmLndyaXRlSW50MzJMRShNYXRoLmZsb29yKHZhbCAqIFNISUZUX1JJR0hUXzMyKSwgdGhpcy5wb3MgKyA0KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gODtcbiAgICB9LFxuXG4gICAgd3JpdGVWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB2YWwgPSArdmFsO1xuXG4gICAgICAgIGlmICh2YWwgPD0gMHg3Zikge1xuICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWw7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgzZmZmKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2MoMik7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAwKSAmIDB4N2YpIHwgMHg4MDtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDcpICYgMHg3Zik7XG5cbiAgICAgICAgfSBlbHNlIGlmICh2YWwgPD0gMHgxZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygzKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2UgaWYgKHZhbCA8PSAweGZmZmZmZmYpIHtcbiAgICAgICAgICAgIHRoaXMucmVhbGxvYyg0KTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKCh2YWwgPj4+IDApICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAoKHZhbCA+Pj4gNykgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAxNCkgJiAweDdmKSB8IDB4ODA7XG4gICAgICAgICAgICB0aGlzLmJ1Zlt0aGlzLnBvcysrXSA9ICgodmFsID4+PiAyMSkgJiAweDdmKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9zO1xuICAgICAgICAgICAgd2hpbGUgKHZhbCA+PSAweDgwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsbG9jKDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gKHZhbCAmIDB4ZmYpIHwgMHg4MDtcbiAgICAgICAgICAgICAgICB2YWwgLz0gMHg4MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhbGxvYygxKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zKytdID0gdmFsIHwgMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyAtIHBvcyA+IDEwKSB0aHJvdyBuZXcgRXJyb3IoJ0dpdmVuIHZhcmludCBkb2VzblxcJ3QgZml0IGludG8gMTAgYnl0ZXMnKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZVNWYXJpbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCA8IDAgPyAtdmFsICogMiAtIDEgOiB2YWwgKiAyKTtcbiAgICB9LFxuXG4gICAgd3JpdGVCb29sZWFuOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludChCb29sZWFuKHZhbCkpO1xuICAgIH0sXG5cbiAgICB3cml0ZVN0cmluZzogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgIHN0ciA9IFN0cmluZyhzdHIpO1xuICAgICAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuYnl0ZUxlbmd0aChzdHIpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KGJ5dGVzKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGJ5dGVzKTtcbiAgICAgICAgdGhpcy5idWYud3JpdGUoc3RyLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IGJ5dGVzO1xuICAgIH0sXG5cbiAgICB3cml0ZUZsb2F0OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZUZsb2F0TEUodmFsLCB0aGlzLnBvcyk7XG4gICAgICAgIHRoaXMucG9zICs9IDQ7XG4gICAgfSxcblxuICAgIHdyaXRlRG91YmxlOiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgICAgICB0aGlzLmJ1Zi53cml0ZURvdWJsZUxFKHZhbCwgdGhpcy5wb3MpO1xuICAgICAgICB0aGlzLnBvcyArPSA4O1xuICAgIH0sXG5cbiAgICB3cml0ZUJ5dGVzOiBmdW5jdGlvbihidWZmZXIpIHtcbiAgICAgICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5yZWFsbG9jKGxlbik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHRoaXMuYnVmW3RoaXMucG9zKytdID0gYnVmZmVyW2ldO1xuICAgIH0sXG5cbiAgICB3cml0ZU1lc3NhZ2U6IGZ1bmN0aW9uKHRhZywgZm4sIG9iaikge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkJ5dGVzKTtcblxuICAgICAgICB0aGlzLnBvcysrOyAvLyByZXNlcnZlIDEgYnl0ZSBmb3Igc2hvcnQgbWVzc2FnZSBsZW5ndGhcblxuICAgICAgICAvLyB3cml0ZSB0aGUgbWVzc2FnZSBkaXJlY3RseSB0byB0aGUgYnVmZmVyIGFuZCBzZWUgaG93IG11Y2ggd2FzIHdyaXR0ZW5cbiAgICAgICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3M7XG4gICAgICAgIGZuKG9iaiwgdGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0aGlzLnBvcyAtIHN0YXJ0UG9zO1xuXG4gICAgICAgIHZhciB2YXJpbnRMZW4gPVxuICAgICAgICAgICAgbGVuIDw9IDB4N2YgPyAxIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDNmZmYgPyAyIDpcbiAgICAgICAgICAgIGxlbiA8PSAweDFmZmZmZiA/IDMgOlxuICAgICAgICAgICAgbGVuIDw9IDB4ZmZmZmZmZiA/IDQgOiBNYXRoLmNlaWwoTWF0aC5sb2cobGVuKSAvIChNYXRoLkxOMiAqIDcpKTtcblxuICAgICAgICAvLyBpZiAxIGJ5dGUgaXNuJ3QgZW5vdWdoIGZvciBlbmNvZGluZyBtZXNzYWdlIGxlbmd0aCwgc2hpZnQgdGhlIGRhdGEgdG8gdGhlIHJpZ2h0XG4gICAgICAgIGlmICh2YXJpbnRMZW4gPiAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWxsb2ModmFyaW50TGVuIC0gMSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5wb3MgLSAxOyBpID49IHN0YXJ0UG9zOyBpLS0pIHRoaXMuYnVmW2kgKyB2YXJpbnRMZW4gLSAxXSA9IHRoaXMuYnVmW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluYWxseSwgd3JpdGUgdGhlIG1lc3NhZ2UgbGVuZ3RoIGluIHRoZSByZXNlcnZlZCBwbGFjZSBhbmQgcmVzdG9yZSB0aGUgcG9zaXRpb25cbiAgICAgICAgdGhpcy5wb3MgPSBzdGFydFBvcyAtIDE7XG4gICAgICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gbGVuO1xuICAgIH0sXG5cbiAgICB3cml0ZVBhY2tlZFZhcmludDogICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkVmFyaW50LCBhcnIpOyAgIH0sXG4gICAgd3JpdGVQYWNrZWRTVmFyaW50OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZFNWYXJpbnQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkQm9vbGVhbjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRCb29sZWFuLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZEZsb2F0OiAgICBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkRmxvYXQsIGFycik7ICAgIH0sXG4gICAgd3JpdGVQYWNrZWREb3VibGU6ICAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZERvdWJsZSwgYXJyKTsgICB9LFxuICAgIHdyaXRlUGFja2VkRml4ZWQzMjogIGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRGaXhlZDMyLCBhcnIpOyAgfSxcbiAgICB3cml0ZVBhY2tlZFNGaXhlZDMyOiBmdW5jdGlvbih0YWcsIGFycikgeyB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIHdyaXRlUGFja2VkU0ZpeGVkMzIsIGFycik7IH0sXG4gICAgd3JpdGVQYWNrZWRGaXhlZDY0OiAgZnVuY3Rpb24odGFnLCBhcnIpIHsgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCB3cml0ZVBhY2tlZEZpeGVkNjQsIGFycik7ICB9LFxuICAgIHdyaXRlUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uKHRhZywgYXJyKSB7IHRoaXMud3JpdGVNZXNzYWdlKHRhZywgd3JpdGVQYWNrZWRTRml4ZWQ2NCwgYXJyKTsgfSxcblxuICAgIHdyaXRlQnl0ZXNGaWVsZDogZnVuY3Rpb24odGFnLCBidWZmZXIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVCeXRlcyhidWZmZXIpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDMyKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDMyRmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQzMik7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQzMih2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVGaXhlZDY0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uKHRhZywgdmFsKSB7XG4gICAgICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgICAgIHRoaXMud3JpdGVTRml4ZWQ2NCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlVmFyaW50KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZVNWYXJpbnRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5WYXJpbnQpO1xuICAgICAgICB0aGlzLndyaXRlU1ZhcmludCh2YWwpO1xuICAgIH0sXG4gICAgd3JpdGVTdHJpbmdGaWVsZDogZnVuY3Rpb24odGFnLCBzdHIpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5CeXRlcyk7XG4gICAgICAgIHRoaXMud3JpdGVTdHJpbmcoc3RyKTtcbiAgICB9LFxuICAgIHdyaXRlRmxvYXRGaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDMyKTtcbiAgICAgICAgdGhpcy53cml0ZUZsb2F0KHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZURvdWJsZUZpZWxkOiBmdW5jdGlvbih0YWcsIHZhbCkge1xuICAgICAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkNjQpO1xuICAgICAgICB0aGlzLndyaXRlRG91YmxlKHZhbCk7XG4gICAgfSxcbiAgICB3cml0ZUJvb2xlYW5GaWVsZDogZnVuY3Rpb24odGFnLCB2YWwpIHtcbiAgICAgICAgdGhpcy53cml0ZVZhcmludEZpZWxkKHRhZywgQm9vbGVhbih2YWwpKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiB3cml0ZVBhY2tlZFZhcmludChhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVWYXJpbnQoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNWYXJpbnQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTVmFyaW50KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZsb2F0KGFyciwgcGJmKSAgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGbG9hdChhcnJbaV0pOyAgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZERvdWJsZShhcnIsIHBiZikgICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVEb3VibGUoYXJyW2ldKTsgICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEJvb2xlYW4oYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVCb29sZWFuKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkMzIoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDMyKGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDMyKGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQzMihhcnJbaV0pOyB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkNjQoYXJyLCBwYmYpICB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVGaXhlZDY0KGFycltpXSk7ICB9XG5mdW5jdGlvbiB3cml0ZVBhY2tlZFNGaXhlZDY0KGFyciwgcGJmKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBwYmYud3JpdGVTRml4ZWQ2NChhcnJbaV0pOyB9XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBvaW50O1xuXG5mdW5jdGlvbiBQb2ludCh4LCB5KSB7XG4gICAgdGhpcy54ID0geDtcbiAgICB0aGlzLnkgPSB5O1xufVxuXG5Qb2ludC5wcm90b3R5cGUgPSB7XG4gICAgY2xvbmU6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgdGhpcy55KTsgfSxcblxuICAgIGFkZDogICAgIGZ1bmN0aW9uKHApIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHApOyAgICAgfSxcbiAgICBzdWI6ICAgICBmdW5jdGlvbihwKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3N1YihwKTsgICAgIH0sXG4gICAgbXVsdDogICAgZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0KGspOyAgICB9LFxuICAgIGRpdjogICAgIGZ1bmN0aW9uKGspIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2KGspOyAgICAgfSxcbiAgICByb3RhdGU6ICBmdW5jdGlvbihhKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZShhKTsgIH0sXG4gICAgbWF0TXVsdDogZnVuY3Rpb24obSkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl9tYXRNdWx0KG0pOyB9LFxuICAgIHVuaXQ6ICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCk7IH0sXG4gICAgcGVycDogICAgZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmNsb25lKCkuX3BlcnAoKTsgfSxcbiAgICByb3VuZDogICBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTsgfSxcblxuICAgIG1hZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQodGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55KTtcbiAgICB9LFxuXG4gICAgZXF1YWxzOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnggPT09IHAueCAmJlxuICAgICAgICAgICAgICAgdGhpcy55ID09PSBwLnk7XG4gICAgfSxcblxuICAgIGRpc3Q6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmRpc3RTcXIocCkpO1xuICAgIH0sXG5cbiAgICBkaXN0U3FyOiBmdW5jdGlvbihwKSB7XG4gICAgICAgIHZhciBkeCA9IHAueCAtIHRoaXMueCxcbiAgICAgICAgICAgIGR5ID0gcC55IC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG4gICAgfSxcblxuICAgIGFuZ2xlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpO1xuICAgIH0sXG5cbiAgICBhbmdsZVRvOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKHRoaXMueSAtIGIueSwgdGhpcy54IC0gYi54KTtcbiAgICB9LFxuXG4gICAgYW5nbGVXaXRoOiBmdW5jdGlvbihiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFuZ2xlV2l0aFNlcChiLngsIGIueSk7XG4gICAgfSxcblxuICAgIC8vIEZpbmQgdGhlIGFuZ2xlIG9mIHRoZSB0d28gdmVjdG9ycywgc29sdmluZyB0aGUgZm9ybXVsYSBmb3IgdGhlIGNyb3NzIHByb2R1Y3QgYSB4IGIgPSB8YXx8YnxzaW4ozrgpIGZvciDOuC5cbiAgICBhbmdsZVdpdGhTZXA6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoXG4gICAgICAgICAgICB0aGlzLnggKiB5IC0gdGhpcy55ICogeCxcbiAgICAgICAgICAgIHRoaXMueCAqIHggKyB0aGlzLnkgKiB5KTtcbiAgICB9LFxuXG4gICAgX21hdE11bHQ6IGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgdmFyIHggPSBtWzBdICogdGhpcy54ICsgbVsxXSAqIHRoaXMueSxcbiAgICAgICAgICAgIHkgPSBtWzJdICogdGhpcy54ICsgbVszXSAqIHRoaXMueTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hZGQ6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54ICs9IHAueDtcbiAgICAgICAgdGhpcy55ICs9IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9zdWI6IGZ1bmN0aW9uKHApIHtcbiAgICAgICAgdGhpcy54IC09IHAueDtcbiAgICAgICAgdGhpcy55IC09IHAueTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9tdWx0OiBmdW5jdGlvbihrKSB7XG4gICAgICAgIHRoaXMueCAqPSBrO1xuICAgICAgICB0aGlzLnkgKj0gaztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9kaXY6IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgdGhpcy54IC89IGs7XG4gICAgICAgIHRoaXMueSAvPSBrO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3VuaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLl9kaXYodGhpcy5tYWcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfcGVycDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55O1xuICAgICAgICB0aGlzLnkgPSB0aGlzLng7XG4gICAgICAgIHRoaXMueCA9IC15O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdGF0ZTogZnVuY3Rpb24oYW5nbGUpIHtcbiAgICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKSxcbiAgICAgICAgICAgIHNpbiA9IE1hdGguc2luKGFuZ2xlKSxcbiAgICAgICAgICAgIHggPSBjb3MgKiB0aGlzLnggLSBzaW4gKiB0aGlzLnksXG4gICAgICAgICAgICB5ID0gc2luICogdGhpcy54ICsgY29zICogdGhpcy55O1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX3JvdW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLnJvdW5kKHRoaXMueSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn07XG5cbi8vIGNvbnN0cnVjdHMgUG9pbnQgZnJvbSBhbiBhcnJheSBpZiBuZWNlc3NhcnlcblBvaW50LmNvbnZlcnQgPSBmdW5jdGlvbiAoYSkge1xuICAgIGlmIChhIGluc3RhbmNlb2YgUG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIHJldHVybiBuZXcgUG9pbnQoYVswXSwgYVsxXSk7XG4gICAgfVxuICAgIHJldHVybiBhO1xufTtcbiIsIi8qXG4gKGMpIDIwMTMsIFZsYWRpbWlyIEFnYWZvbmtpblxuIFJCdXNoLCBhIEphdmFTY3JpcHQgbGlicmFyeSBmb3IgaGlnaC1wZXJmb3JtYW5jZSAyRCBzcGF0aWFsIGluZGV4aW5nIG9mIHBvaW50cyBhbmQgcmVjdGFuZ2xlcy5cbiBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9yYnVzaFxuKi9cblxuKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpIHtcblxuICAgIC8vIGpzaGludCBuZXdjYXA6IGZhbHNlLCB2YWxpZHRoaXM6IHRydWVcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgcmJ1c2gpKSByZXR1cm4gbmV3IHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCk7XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgICB0b0JCb3ggPSB0aGlzLnRvQkJveDtcblxuICAgICAgICBpZiAoIWludGVyc2VjdHMoYmJveCwgbm9kZS5iYm94KSkgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICB2YXIgbm9kZXNUb1NlYXJjaCA9IFtdLFxuICAgICAgICAgICAgaSwgbGVuLCBjaGlsZCwgY2hpbGRCQm94O1xuXG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgY2hpbGRCQm94ID0gbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3g7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJzZWN0cyhiYm94LCBjaGlsZEJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGFpbnMoYmJveCwgY2hpbGRCQm94KSkgdGhpcy5fYWxsKGNoaWxkLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBjb2xsaWRlczogZnVuY3Rpb24gKGJib3gpIHtcblxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZGF0YSxcbiAgICAgICAgICAgIHRvQkJveCA9IHRoaXMudG9CQm94O1xuXG4gICAgICAgIGlmICghaW50ZXJzZWN0cyhiYm94LCBub2RlLmJib3gpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZC5iYm94O1xuXG4gICAgICAgICAgICAgICAgaWYgKGludGVyc2VjdHMoYmJveCwgY2hpbGRCQm94KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IGNvbnRhaW5zKGJib3gsIGNoaWxkQkJveCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1RvU2VhcmNoLnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG5cbiAgICBsb2FkOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBpZiAoIShkYXRhICYmIGRhdGEubGVuZ3RoKSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgdGhpcy5fbWluRW50cmllcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluc2VydChkYXRhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVjdXJzaXZlbHkgYnVpbGQgdGhlIHRyZWUgd2l0aCB0aGUgZ2l2ZW4gZGF0YSBmcm9tIHN0cmF0Y2ggdXNpbmcgT01UIGFsZ29yaXRobVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX2J1aWxkKGRhdGEuc2xpY2UoKSwgMCwgZGF0YS5sZW5ndGggLSAxLCAwKTtcblxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHNhdmUgYXMgaXMgaWYgdHJlZSBpcyBlbXB0eVxuICAgICAgICAgICAgdGhpcy5kYXRhID0gbm9kZTtcblxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPT09IG5vZGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICAvLyBzcGxpdCByb290IGlmIHRyZWVzIGhhdmUgdGhlIHNhbWUgaGVpZ2h0XG4gICAgICAgICAgICB0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLCBub2RlKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5oZWlnaHQgPCBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgdHJlZXMgaWYgaW5zZXJ0ZWQgb25lIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgIHZhciB0bXBOb2RlID0gdGhpcy5kYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IHRtcE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGluc2VydCB0aGUgc21hbGwgdHJlZSBpbnRvIHRoZSBsYXJnZSB0cmVlIGF0IGFwcHJvcHJpYXRlIGxldmVsXG4gICAgICAgICAgICB0aGlzLl9pbnNlcnQobm9kZSwgdGhpcy5kYXRhLmhlaWdodCAtIG5vZGUuaGVpZ2h0IC0gMSwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5zZXJ0OiBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBpZiAoaXRlbSkgdGhpcy5faW5zZXJ0KGl0ZW0sIHRoaXMuZGF0YS5oZWlnaHQgLSAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgICAgIGJib3g6IGVtcHR5KCksXG4gICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICByZW1vdmU6IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBub2RlLmNoaWxkcmVuLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiBjb250YWlucyhub2RlLmJib3gsIGJib3gpKSB7IC8vIGdvIGRvd25cbiAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bMF07XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50KSB7IC8vIGdvIHJpZ2h0XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBwYXJlbnQuY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB9IGVsc2Ugbm9kZSA9IG51bGw7IC8vIG5vdGhpbmcgZm91bmRcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICB0b0JCb3g6IGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBpdGVtOyB9LFxuXG4gICAgY29tcGFyZU1pblg6IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhWzBdIC0gYlswXTsgfSxcbiAgICBjb21wYXJlTWluWTogZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGFbMV0gLSBiWzFdOyB9LFxuXG4gICAgdG9KU09OOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmRhdGE7IH0sXG5cbiAgICBmcm9tSlNPTjogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIF9hbGw6IGZ1bmN0aW9uIChub2RlLCByZXN1bHQpIHtcbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXTtcbiAgICAgICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHJlc3VsdC5wdXNoLmFwcGx5KHJlc3VsdCwgbm9kZS5jaGlsZHJlbik7XG4gICAgICAgICAgICBlbHNlIG5vZGVzVG9TZWFyY2gucHVzaC5hcHBseShub2Rlc1RvU2VhcmNoLCBub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgICAgbm9kZSA9IG5vZGVzVG9TZWFyY2gucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgX2J1aWxkOiBmdW5jdGlvbiAoaXRlbXMsIGxlZnQsIHJpZ2h0LCBoZWlnaHQpIHtcblxuICAgICAgICB2YXIgTiA9IHJpZ2h0IC0gbGVmdCArIDEsXG4gICAgICAgICAgICBNID0gdGhpcy5fbWF4RW50cmllcyxcbiAgICAgICAgICAgIG5vZGU7XG5cbiAgICAgICAgaWYgKE4gPD0gTSkge1xuICAgICAgICAgICAgLy8gcmVhY2hlZCBsZWFmIGxldmVsOyByZXR1cm4gbGVhZlxuICAgICAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgICAgICBjaGlsZHJlbjogaXRlbXMuc2xpY2UobGVmdCwgcmlnaHQgKyAxKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgICAgICAgICAgYmJveDogbnVsbCxcbiAgICAgICAgICAgICAgICBsZWFmOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgLy8gdGFyZ2V0IGhlaWdodCBvZiB0aGUgYnVsay1sb2FkZWQgdHJlZVxuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGgubG9nKE4pIC8gTWF0aC5sb2coTSkpO1xuXG4gICAgICAgICAgICAvLyB0YXJnZXQgbnVtYmVyIG9mIHJvb3QgZW50cmllcyB0byBtYXhpbWl6ZSBzdG9yYWdlIHV0aWxpemF0aW9uXG4gICAgICAgICAgICBNID0gTWF0aC5jZWlsKE4gLyBNYXRoLnBvdyhNLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPIGVsaW1pbmF0ZSByZWN1cnNpb24/XG5cbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgYmJveDogbnVsbFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNwbGl0IHRoZSBpdGVtcyBpbnRvIE0gbW9zdGx5IHNxdWFyZSB0aWxlc1xuXG4gICAgICAgIHZhciBOMiA9IE1hdGguY2VpbChOIC8gTSksXG4gICAgICAgICAgICBOMSA9IE4yICogTWF0aC5jZWlsKE1hdGguc3FydChNKSksXG4gICAgICAgICAgICBpLCBqLCByaWdodDIsIHJpZ2h0MztcblxuICAgICAgICBtdWx0aVNlbGVjdChpdGVtcywgbGVmdCwgcmlnaHQsIE4xLCB0aGlzLmNvbXBhcmVNaW5YKTtcblxuICAgICAgICBmb3IgKGkgPSBsZWZ0OyBpIDw9IHJpZ2h0OyBpICs9IE4xKSB7XG5cbiAgICAgICAgICAgIHJpZ2h0MiA9IE1hdGgubWluKGkgKyBOMSAtIDEsIHJpZ2h0KTtcblxuICAgICAgICAgICAgbXVsdGlTZWxlY3QoaXRlbXMsIGksIHJpZ2h0MiwgTjIsIHRoaXMuY29tcGFyZU1pblkpO1xuXG4gICAgICAgICAgICBmb3IgKGogPSBpOyBqIDw9IHJpZ2h0MjsgaiArPSBOMikge1xuXG4gICAgICAgICAgICAgICAgcmlnaHQzID0gTWF0aC5taW4oaiArIE4yIC0gMSwgcmlnaHQyKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgZWFjaCBlbnRyeSByZWN1cnNpdmVseVxuICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4ucHVzaCh0aGlzLl9idWlsZChpdGVtcywgaiwgcmlnaHQzLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjYWxjQkJveChub2RlLCB0aGlzLnRvQkJveCk7XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9jaG9vc2VTdWJ0cmVlOiBmdW5jdGlvbiAoYmJveCwgbm9kZSwgbGV2ZWwsIHBhdGgpIHtcblxuICAgICAgICB2YXIgaSwgbGVuLCBjaGlsZCwgdGFyZ2V0Tm9kZSwgYXJlYSwgZW5sYXJnZW1lbnQsIG1pbkFyZWEsIG1pbkVubGFyZ2VtZW50O1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYgfHwgcGF0aC5sZW5ndGggLSAxID09PSBsZXZlbCkgYnJlYWs7XG5cbiAgICAgICAgICAgIG1pbkFyZWEgPSBtaW5FbmxhcmdlbWVudCA9IEluZmluaXR5O1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShjaGlsZC5iYm94KTtcbiAgICAgICAgICAgICAgICBlbmxhcmdlbWVudCA9IGVubGFyZ2VkQXJlYShiYm94LCBjaGlsZC5iYm94KSAtIGFyZWE7XG5cbiAgICAgICAgICAgICAgICAvLyBjaG9vc2UgZW50cnkgd2l0aCB0aGUgbGVhc3QgYXJlYSBlbmxhcmdlbWVudFxuICAgICAgICAgICAgICAgIGlmIChlbmxhcmdlbWVudCA8IG1pbkVubGFyZ2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkVubGFyZ2VtZW50ID0gZW5sYXJnZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVubGFyZ2VtZW50ID09PSBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIG9uZSB3aXRoIHRoZSBzbWFsbGVzdCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSB0YXJnZXROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcblxuICAgIF9pbnNlcnQ6IGZ1bmN0aW9uIChpdGVtLCBsZXZlbCwgaXNOb2RlKSB7XG5cbiAgICAgICAgdmFyIHRvQkJveCA9IHRoaXMudG9CQm94LFxuICAgICAgICAgICAgYmJveCA9IGlzTm9kZSA/IGl0ZW0uYmJveCA6IHRvQkJveChpdGVtKSxcbiAgICAgICAgICAgIGluc2VydFBhdGggPSBbXTtcblxuICAgICAgICAvLyBmaW5kIHRoZSBiZXN0IG5vZGUgZm9yIGFjY29tbW9kYXRpbmcgdGhlIGl0ZW0sIHNhdmluZyBhbGwgbm9kZXMgYWxvbmcgdGhlIHBhdGggdG9vXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fY2hvb3NlU3VidHJlZShiYm94LCB0aGlzLmRhdGEsIGxldmVsLCBpbnNlcnRQYXRoKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGl0ZW0gaW50byB0aGUgbm9kZVxuICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goaXRlbSk7XG4gICAgICAgIGV4dGVuZChub2RlLmJib3gsIGJib3gpO1xuXG4gICAgICAgIC8vIHNwbGl0IG9uIG5vZGUgb3ZlcmZsb3c7IHByb3BhZ2F0ZSB1cHdhcmRzIGlmIG5lY2Vzc2FyeVxuICAgICAgICB3aGlsZSAobGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAgaWYgKGluc2VydFBhdGhbbGV2ZWxdLmNoaWxkcmVuLmxlbmd0aCA+IHRoaXMuX21heEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zcGxpdChpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgICAgICAgICAgICAgbGV2ZWwtLTtcbiAgICAgICAgICAgIH0gZWxzZSBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBiYm94ZXMgYWxvbmcgdGhlIGluc2VydGlvbiBwYXRoXG4gICAgICAgIHRoaXMuX2FkanVzdFBhcmVudEJCb3hlcyhiYm94LCBpbnNlcnRQYXRoLCBsZXZlbCk7XG4gICAgfSxcblxuICAgIC8vIHNwbGl0IG92ZXJmbG93ZWQgbm9kZSBpbnRvIHR3b1xuICAgIF9zcGxpdDogZnVuY3Rpb24gKGluc2VydFBhdGgsIGxldmVsKSB7XG5cbiAgICAgICAgdmFyIG5vZGUgPSBpbnNlcnRQYXRoW2xldmVsXSxcbiAgICAgICAgICAgIE0gPSBub2RlLmNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICAgIG0gPSB0aGlzLl9taW5FbnRyaWVzO1xuXG4gICAgICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhub2RlLCBtLCBNKTtcblxuICAgICAgICB2YXIgbmV3Tm9kZSA9IHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLnNwbGljZSh0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pKSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobm9kZS5sZWFmKSBuZXdOb2RlLmxlYWYgPSB0cnVlO1xuXG4gICAgICAgIGNhbGNCQm94KG5vZGUsIHRoaXMudG9CQm94KTtcbiAgICAgICAgY2FsY0JCb3gobmV3Tm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIGlmIChsZXZlbCkgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIGVsc2UgdGhpcy5fc3BsaXRSb290KG5vZGUsIG5ld05vZGUpO1xuICAgIH0sXG5cbiAgICBfc3BsaXRSb290OiBmdW5jdGlvbiAobm9kZSwgbmV3Tm9kZSkge1xuICAgICAgICAvLyBzcGxpdCByb290IG5vZGVcbiAgICAgICAgdGhpcy5kYXRhID0ge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtub2RlLCBuZXdOb2RlXSxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZS5oZWlnaHQgKyAxXG4gICAgICAgIH07XG4gICAgICAgIGNhbGNCQm94KHRoaXMuZGF0YSwgdGhpcy50b0JCb3gpO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3BsaXRJbmRleDogZnVuY3Rpb24gKG5vZGUsIG0sIE0pIHtcblxuICAgICAgICB2YXIgaSwgYmJveDEsIGJib3gyLCBvdmVybGFwLCBhcmVhLCBtaW5PdmVybGFwLCBtaW5BcmVhLCBpbmRleDtcblxuICAgICAgICBtaW5PdmVybGFwID0gbWluQXJlYSA9IEluZmluaXR5O1xuXG4gICAgICAgIGZvciAoaSA9IG07IGkgPD0gTSAtIG07IGkrKykge1xuICAgICAgICAgICAgYmJveDEgPSBkaXN0QkJveChub2RlLCAwLCBpLCB0aGlzLnRvQkJveCk7XG4gICAgICAgICAgICBiYm94MiA9IGRpc3RCQm94KG5vZGUsIGksIE0sIHRoaXMudG9CQm94KTtcblxuICAgICAgICAgICAgb3ZlcmxhcCA9IGludGVyc2VjdGlvbkFyZWEoYmJveDEsIGJib3gyKTtcbiAgICAgICAgICAgIGFyZWEgPSBiYm94QXJlYShiYm94MSkgKyBiYm94QXJlYShiYm94Mik7XG5cbiAgICAgICAgICAgIC8vIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIG92ZXJsYXBcbiAgICAgICAgICAgIGlmIChvdmVybGFwIDwgbWluT3ZlcmxhcCkge1xuICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSBvdmVybGFwO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcblxuICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG92ZXJsYXAgPT09IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIGRpc3RyaWJ1dGlvbiB3aXRoIG1pbmltdW0gYXJlYVxuICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICB9LFxuXG4gICAgLy8gc29ydHMgbm9kZSBjaGlsZHJlbiBieSB0aGUgYmVzdCBheGlzIGZvciBzcGxpdFxuICAgIF9jaG9vc2VTcGxpdEF4aXM6IGZ1bmN0aW9uIChub2RlLCBtLCBNKSB7XG5cbiAgICAgICAgdmFyIGNvbXBhcmVNaW5YID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWCA6IGNvbXBhcmVOb2RlTWluWCxcbiAgICAgICAgICAgIGNvbXBhcmVNaW5ZID0gbm9kZS5sZWFmID8gdGhpcy5jb21wYXJlTWluWSA6IGNvbXBhcmVOb2RlTWluWSxcbiAgICAgICAgICAgIHhNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5YKSxcbiAgICAgICAgICAgIHlNYXJnaW4gPSB0aGlzLl9hbGxEaXN0TWFyZ2luKG5vZGUsIG0sIE0sIGNvbXBhcmVNaW5ZKTtcblxuICAgICAgICAvLyBpZiB0b3RhbCBkaXN0cmlidXRpb25zIG1hcmdpbiB2YWx1ZSBpcyBtaW5pbWFsIGZvciB4LCBzb3J0IGJ5IG1pblgsXG4gICAgICAgIC8vIG90aGVyd2lzZSBpdCdzIGFscmVhZHkgc29ydGVkIGJ5IG1pbllcbiAgICAgICAgaWYgKHhNYXJnaW4gPCB5TWFyZ2luKSBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZU1pblgpO1xuICAgIH0sXG5cbiAgICAvLyB0b3RhbCBtYXJnaW4gb2YgYWxsIHBvc3NpYmxlIHNwbGl0IGRpc3RyaWJ1dGlvbnMgd2hlcmUgZWFjaCBub2RlIGlzIGF0IGxlYXN0IG0gZnVsbFxuICAgIF9hbGxEaXN0TWFyZ2luOiBmdW5jdGlvbiAobm9kZSwgbSwgTSwgY29tcGFyZSkge1xuXG4gICAgICAgIG5vZGUuY2hpbGRyZW4uc29ydChjb21wYXJlKTtcblxuICAgICAgICB2YXIgdG9CQm94ID0gdGhpcy50b0JCb3gsXG4gICAgICAgICAgICBsZWZ0QkJveCA9IGRpc3RCQm94KG5vZGUsIDAsIG0sIHRvQkJveCksXG4gICAgICAgICAgICByaWdodEJCb3ggPSBkaXN0QkJveChub2RlLCBNIC0gbSwgTSwgdG9CQm94KSxcbiAgICAgICAgICAgIG1hcmdpbiA9IGJib3hNYXJnaW4obGVmdEJCb3gpICsgYmJveE1hcmdpbihyaWdodEJCb3gpLFxuICAgICAgICAgICAgaSwgY2hpbGQ7XG5cbiAgICAgICAgZm9yIChpID0gbTsgaSA8IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGV4dGVuZChsZWZ0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4obGVmdEJCb3gpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gTSAtIG0gLSAxOyBpID49IG07IGktLSkge1xuICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgZXh0ZW5kKHJpZ2h0QkJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4ocmlnaHRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXJnaW47XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgZXh0ZW5kKHBhdGhbaV0uYmJveCwgYmJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2NvbmRlbnNlOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIHRoZSBwYXRoLCByZW1vdmluZyBlbXB0eSBub2RlcyBhbmQgdXBkYXRpbmcgYmJveGVzXG4gICAgICAgIGZvciAodmFyIGkgPSBwYXRoLmxlbmd0aCAtIDEsIHNpYmxpbmdzOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKHBhdGhbaV0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzID0gcGF0aFtpIC0gMV0uY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHNpYmxpbmdzLnNwbGljZShzaWJsaW5ncy5pbmRleE9mKHBhdGhbaV0pLCAxKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBjYWxjQkJveChwYXRoW2ldLCB0aGlzLnRvQkJveCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgX2luaXRGb3JtYXQ6IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgLy8gZGF0YSBmb3JtYXQgKG1pblgsIG1pblksIG1heFgsIG1heFkgYWNjZXNzb3JzKVxuXG4gICAgICAgIC8vIHVzZXMgZXZhbC10eXBlIGZ1bmN0aW9uIGNvbXBpbGF0aW9uIGluc3RlYWQgb2YganVzdCBhY2NlcHRpbmcgYSB0b0JCb3ggZnVuY3Rpb25cbiAgICAgICAgLy8gYmVjYXVzZSB0aGUgYWxnb3JpdGhtcyBhcmUgdmVyeSBzZW5zaXRpdmUgdG8gc29ydGluZyBmdW5jdGlvbnMgcGVyZm9ybWFuY2UsXG4gICAgICAgIC8vIHNvIHRoZXkgc2hvdWxkIGJlIGRlYWQgc2ltcGxlIGFuZCB3aXRob3V0IGlubmVyIGNhbGxzXG5cbiAgICAgICAgLy8ganNoaW50IGV2aWw6IHRydWVcblxuICAgICAgICB2YXIgY29tcGFyZUFyciA9IFsncmV0dXJuIGEnLCAnIC0gYicsICc7J107XG5cbiAgICAgICAgdGhpcy5jb21wYXJlTWluWCA9IG5ldyBGdW5jdGlvbignYScsICdiJywgY29tcGFyZUFyci5qb2luKGZvcm1hdFswXSkpO1xuICAgICAgICB0aGlzLmNvbXBhcmVNaW5ZID0gbmV3IEZ1bmN0aW9uKCdhJywgJ2InLCBjb21wYXJlQXJyLmpvaW4oZm9ybWF0WzFdKSk7XG5cbiAgICAgICAgdGhpcy50b0JCb3ggPSBuZXcgRnVuY3Rpb24oJ2EnLCAncmV0dXJuIFthJyArIGZvcm1hdC5qb2luKCcsIGEnKSArICddOycpO1xuICAgIH1cbn07XG5cblxuLy8gY2FsY3VsYXRlIG5vZGUncyBiYm94IGZyb20gYmJveGVzIG9mIGl0cyBjaGlsZHJlblxuZnVuY3Rpb24gY2FsY0JCb3gobm9kZSwgdG9CQm94KSB7XG4gICAgbm9kZS5iYm94ID0gZGlzdEJCb3gobm9kZSwgMCwgbm9kZS5jaGlsZHJlbi5sZW5ndGgsIHRvQkJveCk7XG59XG5cbi8vIG1pbiBib3VuZGluZyByZWN0YW5nbGUgb2Ygbm9kZSBjaGlsZHJlbiBmcm9tIGsgdG8gcC0xXG5mdW5jdGlvbiBkaXN0QkJveChub2RlLCBrLCBwLCB0b0JCb3gpIHtcbiAgICB2YXIgYmJveCA9IGVtcHR5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICBleHRlbmQoYmJveCwgbm9kZS5sZWFmID8gdG9CQm94KGNoaWxkKSA6IGNoaWxkLmJib3gpO1xuICAgIH1cblxuICAgIHJldHVybiBiYm94O1xufVxuXG5mdW5jdGlvbiBlbXB0eSgpIHsgcmV0dXJuIFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsgfVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGFbMF0gPSBNYXRoLm1pbihhWzBdLCBiWzBdKTtcbiAgICBhWzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSk7XG4gICAgYVsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pO1xuICAgIGFbM10gPSBNYXRoLm1heChhWzNdLCBiWzNdKTtcbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5YKGEsIGIpIHsgcmV0dXJuIGEuYmJveFswXSAtIGIuYmJveFswXTsgfVxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5ZKGEsIGIpIHsgcmV0dXJuIGEuYmJveFsxXSAtIGIuYmJveFsxXTsgfVxuXG5mdW5jdGlvbiBiYm94QXJlYShhKSAgIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKiAoYVszXSAtIGFbMV0pOyB9XG5mdW5jdGlvbiBiYm94TWFyZ2luKGEpIHsgcmV0dXJuIChhWzJdIC0gYVswXSkgKyAoYVszXSAtIGFbMV0pOyB9XG5cbmZ1bmN0aW9uIGVubGFyZ2VkQXJlYShhLCBiKSB7XG4gICAgcmV0dXJuIChNYXRoLm1heChiWzJdLCBhWzJdKSAtIE1hdGgubWluKGJbMF0sIGFbMF0pKSAqXG4gICAgICAgICAgIChNYXRoLm1heChiWzNdLCBhWzNdKSAtIE1hdGgubWluKGJbMV0sIGFbMV0pKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uQXJlYShhLCBiKSB7XG4gICAgdmFyIG1pblggPSBNYXRoLm1heChhWzBdLCBiWzBdKSxcbiAgICAgICAgbWluWSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pLFxuICAgICAgICBtYXhYID0gTWF0aC5taW4oYVsyXSwgYlsyXSksXG4gICAgICAgIG1heFkgPSBNYXRoLm1pbihhWzNdLCBiWzNdKTtcblxuICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICBNYXRoLm1heCgwLCBtYXhZIC0gbWluWSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSA8PSBiWzBdICYmXG4gICAgICAgICAgIGFbMV0gPD0gYlsxXSAmJlxuICAgICAgICAgICBiWzJdIDw9IGFbMl0gJiZcbiAgICAgICAgICAgYlszXSA8PSBhWzNdO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RzKGEsIGIpIHtcbiAgICByZXR1cm4gYlswXSA8PSBhWzJdICYmXG4gICAgICAgICAgIGJbMV0gPD0gYVszXSAmJlxuICAgICAgICAgICBiWzJdID49IGFbMF0gJiZcbiAgICAgICAgICAgYlszXSA+PSBhWzFdO1xufVxuXG4vLyBzb3J0IGFuIGFycmF5IHNvIHRoYXQgaXRlbXMgY29tZSBpbiBncm91cHMgb2YgbiB1bnNvcnRlZCBpdGVtcywgd2l0aCBncm91cHMgc29ydGVkIGJldHdlZW4gZWFjaCBvdGhlcjtcbi8vIGNvbWJpbmVzIHNlbGVjdGlvbiBhbGdvcml0aG0gd2l0aCBiaW5hcnkgZGl2aWRlICYgY29ucXVlciBhcHByb2FjaFxuXG5mdW5jdGlvbiBtdWx0aVNlbGVjdChhcnIsIGxlZnQsIHJpZ2h0LCBuLCBjb21wYXJlKSB7XG4gICAgdmFyIHN0YWNrID0gW2xlZnQsIHJpZ2h0XSxcbiAgICAgICAgbWlkO1xuXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgICAgICByaWdodCA9IHN0YWNrLnBvcCgpO1xuICAgICAgICBsZWZ0ID0gc3RhY2sucG9wKCk7XG5cbiAgICAgICAgaWYgKHJpZ2h0IC0gbGVmdCA8PSBuKSBjb250aW51ZTtcblxuICAgICAgICBtaWQgPSBsZWZ0ICsgTWF0aC5jZWlsKChyaWdodCAtIGxlZnQpIC8gbiAvIDIpICogbjtcbiAgICAgICAgc2VsZWN0KGFyciwgbGVmdCwgcmlnaHQsIG1pZCwgY29tcGFyZSk7XG5cbiAgICAgICAgc3RhY2sucHVzaChsZWZ0LCBtaWQsIG1pZCwgcmlnaHQpO1xuICAgIH1cbn1cblxuLy8gRmxveWQtUml2ZXN0IHNlbGVjdGlvbiBhbGdvcml0aG06XG4vLyBzb3J0IGFuIGFycmF5IGJldHdlZW4gbGVmdCBhbmQgcmlnaHQgKGluY2x1c2l2ZSkgc28gdGhhdCB0aGUgc21hbGxlc3QgayBlbGVtZW50cyBjb21lIGZpcnN0ICh1bm9yZGVyZWQpXG5mdW5jdGlvbiBzZWxlY3QoYXJyLCBsZWZ0LCByaWdodCwgaywgY29tcGFyZSkge1xuICAgIHZhciBuLCBpLCB6LCBzLCBzZCwgbmV3TGVmdCwgbmV3UmlnaHQsIHQsIGo7XG5cbiAgICB3aGlsZSAocmlnaHQgPiBsZWZ0KSB7XG4gICAgICAgIGlmIChyaWdodCAtIGxlZnQgPiA2MDApIHtcbiAgICAgICAgICAgIG4gPSByaWdodCAtIGxlZnQgKyAxO1xuICAgICAgICAgICAgaSA9IGsgLSBsZWZ0ICsgMTtcbiAgICAgICAgICAgIHogPSBNYXRoLmxvZyhuKTtcbiAgICAgICAgICAgIHMgPSAwLjUgKiBNYXRoLmV4cCgyICogeiAvIDMpO1xuICAgICAgICAgICAgc2QgPSAwLjUgKiBNYXRoLnNxcnQoeiAqIHMgKiAobiAtIHMpIC8gbikgKiAoaSAtIG4gLyAyIDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBuZXdMZWZ0ID0gTWF0aC5tYXgobGVmdCwgTWF0aC5mbG9vcihrIC0gaSAqIHMgLyBuICsgc2QpKTtcbiAgICAgICAgICAgIG5ld1JpZ2h0ID0gTWF0aC5taW4ocmlnaHQsIE1hdGguZmxvb3IoayArIChuIC0gaSkgKiBzIC8gbiArIHNkKSk7XG4gICAgICAgICAgICBzZWxlY3QoYXJyLCBuZXdMZWZ0LCBuZXdSaWdodCwgaywgY29tcGFyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0ID0gYXJyW2tdO1xuICAgICAgICBpID0gbGVmdDtcbiAgICAgICAgaiA9IHJpZ2h0O1xuXG4gICAgICAgIHN3YXAoYXJyLCBsZWZ0LCBrKTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYXJyW3JpZ2h0XSwgdCkgPiAwKSBzd2FwKGFyciwgbGVmdCwgcmlnaHQpO1xuXG4gICAgICAgIHdoaWxlIChpIDwgaikge1xuICAgICAgICAgICAgc3dhcChhcnIsIGksIGopO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgd2hpbGUgKGNvbXBhcmUoYXJyW2ldLCB0KSA8IDApIGkrKztcbiAgICAgICAgICAgIHdoaWxlIChjb21wYXJlKGFycltqXSwgdCkgPiAwKSBqLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29tcGFyZShhcnJbbGVmdF0sIHQpID09PSAwKSBzd2FwKGFyciwgbGVmdCwgaik7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgc3dhcChhcnIsIGosIHJpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqIDw9IGspIGxlZnQgPSBqICsgMTtcbiAgICAgICAgaWYgKGsgPD0gaikgcmlnaHQgPSBqIC0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoYXJyLCBpLCBqKSB7XG4gICAgdmFyIHRtcCA9IGFycltpXTtcbiAgICBhcnJbaV0gPSBhcnJbal07XG4gICAgYXJyW2pdID0gdG1wO1xufVxuXG5cbi8vIGV4cG9ydCBhcyBBTUQvQ29tbW9uSlMgbW9kdWxlIG9yIGdsb2JhbCB2YXJpYWJsZVxuaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgZGVmaW5lKCdyYnVzaCcsIGZ1bmN0aW9uKCkgeyByZXR1cm4gcmJ1c2g7IH0pO1xuZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpIG1vZHVsZS5leHBvcnRzID0gcmJ1c2g7XG5lbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHNlbGYucmJ1c2ggPSByYnVzaDtcbmVsc2Ugd2luZG93LnJidXNoID0gcmJ1c2g7XG5cbn0pKCk7XG4iLCIvLyBDb3B5cmlnaHQgMjAxNCBTaW1vbiBMeWRlbGxcclxuLy8gWDExICjigJxNSVTigJ0pIExpY2Vuc2VkLiAoU2VlIExJQ0VOU0UuKVxyXG5cclxudm9pZCAoZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkge1xyXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xyXG4gICAgZGVmaW5lKGZhY3RvcnkpXHJcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KClcclxuICB9IGVsc2Uge1xyXG4gICAgcm9vdC5yZXNvbHZlVXJsID0gZmFjdG9yeSgpXHJcbiAgfVxyXG59KHRoaXMsIGZ1bmN0aW9uKCkge1xyXG5cclxuICBmdW5jdGlvbiByZXNvbHZlVXJsKC8qIC4uLnVybHMgKi8pIHtcclxuICAgIHZhciBudW1VcmxzID0gYXJndW1lbnRzLmxlbmd0aFxyXG5cclxuICAgIGlmIChudW1VcmxzID09PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInJlc29sdmVVcmwgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50OyBnb3Qgbm9uZS5cIilcclxuICAgIH1cclxuXHJcbiAgICB2YXIgYmFzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiYXNlXCIpXHJcbiAgICBiYXNlLmhyZWYgPSBhcmd1bWVudHNbMF1cclxuXHJcbiAgICBpZiAobnVtVXJscyA9PT0gMSkge1xyXG4gICAgICByZXR1cm4gYmFzZS5ocmVmXHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImhlYWRcIilbMF1cclxuICAgIGhlYWQuaW5zZXJ0QmVmb3JlKGJhc2UsIGhlYWQuZmlyc3RDaGlsZClcclxuXHJcbiAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpXHJcbiAgICB2YXIgcmVzb2x2ZWRcclxuXHJcbiAgICBmb3IgKHZhciBpbmRleCA9IDE7IGluZGV4IDwgbnVtVXJsczsgaW5kZXgrKykge1xyXG4gICAgICBhLmhyZWYgPSBhcmd1bWVudHNbaW5kZXhdXHJcbiAgICAgIHJlc29sdmVkID0gYS5ocmVmXHJcbiAgICAgIGJhc2UuaHJlZiA9IHJlc29sdmVkXHJcbiAgICB9XHJcblxyXG4gICAgaGVhZC5yZW1vdmVDaGlsZChiYXNlKVxyXG5cclxuICAgIHJldHVybiByZXNvbHZlZFxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc29sdmVVcmxcclxuXHJcbn0pKTtcclxuIiwiLypcbiAqIENvcHlyaWdodCAoQykgMjAwOCBBcHBsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnNcbiAqIGFyZSBtZXQ6XG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodFxuICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGVcbiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIGBgQVMgSVMnJyBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuICogSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSXG4gKiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgQVBQTEUgSU5DLiBPUlxuICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sXG4gKiBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1JcbiAqIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gKiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICpcbiAqIFBvcnRlZCBmcm9tIFdlYmtpdFxuICogaHR0cDovL3N2bi53ZWJraXQub3JnL3JlcG9zaXRvcnkvd2Via2l0L3RydW5rL1NvdXJjZS9XZWJDb3JlL3BsYXRmb3JtL2dyYXBoaWNzL1VuaXRCZXppZXIuaFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gVW5pdEJlemllcjtcblxuZnVuY3Rpb24gVW5pdEJlemllcihwMXgsIHAxeSwgcDJ4LCBwMnkpIHtcbiAgICAvLyBDYWxjdWxhdGUgdGhlIHBvbHlub21pYWwgY29lZmZpY2llbnRzLCBpbXBsaWNpdCBmaXJzdCBhbmQgbGFzdCBjb250cm9sIHBvaW50cyBhcmUgKDAsMCkgYW5kICgxLDEpLlxuICAgIHRoaXMuY3ggPSAzLjAgKiBwMXg7XG4gICAgdGhpcy5ieCA9IDMuMCAqIChwMnggLSBwMXgpIC0gdGhpcy5jeDtcbiAgICB0aGlzLmF4ID0gMS4wIC0gdGhpcy5jeCAtIHRoaXMuYng7XG5cbiAgICB0aGlzLmN5ID0gMy4wICogcDF5O1xuICAgIHRoaXMuYnkgPSAzLjAgKiAocDJ5IC0gcDF5KSAtIHRoaXMuY3k7XG4gICAgdGhpcy5heSA9IDEuMCAtIHRoaXMuY3kgLSB0aGlzLmJ5O1xuXG4gICAgdGhpcy5wMXggPSBwMXg7XG4gICAgdGhpcy5wMXkgPSBwMnk7XG4gICAgdGhpcy5wMnggPSBwMng7XG4gICAgdGhpcy5wMnkgPSBwMnk7XG59XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWCA9IGZ1bmN0aW9uKHQpIHtcbiAgICAvLyBgYXggdF4zICsgYnggdF4yICsgY3ggdCcgZXhwYW5kZWQgdXNpbmcgSG9ybmVyJ3MgcnVsZS5cbiAgICByZXR1cm4gKCh0aGlzLmF4ICogdCArIHRoaXMuYngpICogdCArIHRoaXMuY3gpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlWSA9IGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gKCh0aGlzLmF5ICogdCArIHRoaXMuYnkpICogdCArIHRoaXMuY3kpICogdDtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVggPSBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuICgzLjAgKiB0aGlzLmF4ICogdCArIDIuMCAqIHRoaXMuYngpICogdCArIHRoaXMuY3g7XG59O1xuXG5Vbml0QmV6aWVyLnByb3RvdHlwZS5zb2x2ZUN1cnZlWCA9IGZ1bmN0aW9uKHgsIGVwc2lsb24pIHtcbiAgICBpZiAodHlwZW9mIGVwc2lsb24gPT09ICd1bmRlZmluZWQnKSBlcHNpbG9uID0gMWUtNjtcblxuICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgaTtcblxuICAgIC8vIEZpcnN0IHRyeSBhIGZldyBpdGVyYXRpb25zIG9mIE5ld3RvbidzIG1ldGhvZCAtLSBub3JtYWxseSB2ZXJ5IGZhc3QuXG4gICAgZm9yICh0MiA9IHgsIGkgPSAwOyBpIDwgODsgaSsrKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0MikgLSB4O1xuICAgICAgICBpZiAoTWF0aC5hYnMoeDIpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIHZhciBkMiA9IHRoaXMuc2FtcGxlQ3VydmVEZXJpdmF0aXZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyhkMikgPCAxZS02KSBicmVhaztcblxuICAgICAgICB0MiA9IHQyIC0geDIgLyBkMjtcbiAgICB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gdGhlIGJpc2VjdGlvbiBtZXRob2QgZm9yIHJlbGlhYmlsaXR5LlxuICAgIHQwID0gMC4wO1xuICAgIHQxID0gMS4wO1xuICAgIHQyID0geDtcblxuICAgIGlmICh0MiA8IHQwKSByZXR1cm4gdDA7XG4gICAgaWYgKHQyID4gdDEpIHJldHVybiB0MTtcblxuICAgIHdoaWxlICh0MCA8IHQxKSB7XG5cbiAgICAgICAgeDIgPSB0aGlzLnNhbXBsZUN1cnZlWCh0Mik7XG4gICAgICAgIGlmIChNYXRoLmFicyh4MiAtIHgpIDwgZXBzaWxvbikgcmV0dXJuIHQyO1xuXG4gICAgICAgIGlmICh4ID4geDIpIHtcbiAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0MSA9IHQyO1xuICAgICAgICB9XG5cbiAgICAgICAgdDIgPSAodDEgLSB0MCkgKiAwLjUgKyB0MDtcbiAgICB9XG5cbiAgICAvLyBGYWlsdXJlLlxuICAgIHJldHVybiB0Mjtcbn07XG5cblVuaXRCZXppZXIucHJvdG90eXBlLnNvbHZlID0gZnVuY3Rpb24oeCwgZXBzaWxvbikge1xuICAgIHJldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHgsIGVwc2lsb24pKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cy5WZWN0b3JUaWxlID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUZlYXR1cmUgPSByZXF1aXJlKCcuL2xpYi92ZWN0b3J0aWxlZmVhdHVyZS5qcycpO1xubW9kdWxlLmV4cG9ydHMuVmVjdG9yVGlsZUxheWVyID0gcmVxdWlyZSgnLi9saWIvdmVjdG9ydGlsZWxheWVyLmpzJyk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlTGF5ZXIgPSByZXF1aXJlKCcuL3ZlY3RvcnRpbGVsYXllcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZlY3RvclRpbGU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGUocGJmLCBlbmQpIHtcbiAgICB0aGlzLmxheWVycyA9IHBiZi5yZWFkRmllbGRzKHJlYWRUaWxlLCB7fSwgZW5kKTtcbn1cblxuZnVuY3Rpb24gcmVhZFRpbGUodGFnLCBsYXllcnMsIHBiZikge1xuICAgIGlmICh0YWcgPT09IDMpIHtcbiAgICAgICAgdmFyIGxheWVyID0gbmV3IFZlY3RvclRpbGVMYXllcihwYmYsIHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zKTtcbiAgICAgICAgaWYgKGxheWVyLmxlbmd0aCkgbGF5ZXJzW2xheWVyLm5hbWVdID0gbGF5ZXI7XG4gICAgfVxufVxuXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJ3BvaW50LWdlb21ldHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gVmVjdG9yVGlsZUZlYXR1cmU7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVGZWF0dXJlKHBiZiwgZW5kLCBleHRlbnQsIGtleXMsIHZhbHVlcykge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMucHJvcGVydGllcyA9IHt9O1xuICAgIHRoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIHRoaXMudHlwZSA9IDA7XG5cbiAgICAvLyBQcml2YXRlXG4gICAgdGhpcy5fcGJmID0gcGJmO1xuICAgIHRoaXMuX2dlb21ldHJ5ID0gLTE7XG4gICAgdGhpcy5fa2V5cyA9IGtleXM7XG4gICAgdGhpcy5fdmFsdWVzID0gdmFsdWVzO1xuXG4gICAgcGJmLnJlYWRGaWVsZHMocmVhZEZlYXR1cmUsIHRoaXMsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRGZWF0dXJlKHRhZywgZmVhdHVyZSwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PSAxKSBmZWF0dXJlLl9pZCA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgZWxzZSBpZiAodGFnID09IDIpIHJlYWRUYWcocGJmLCBmZWF0dXJlKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gMykgZmVhdHVyZS50eXBlID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICBlbHNlIGlmICh0YWcgPT0gNCkgZmVhdHVyZS5fZ2VvbWV0cnkgPSBwYmYucG9zO1xufVxuXG5mdW5jdGlvbiByZWFkVGFnKHBiZiwgZmVhdHVyZSkge1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIHZhciBrZXkgPSBmZWF0dXJlLl9rZXlzW3BiZi5yZWFkVmFyaW50KCldLFxuICAgICAgICAgICAgdmFsdWUgPSBmZWF0dXJlLl92YWx1ZXNbcGJmLnJlYWRWYXJpbnQoKV07XG4gICAgICAgIGZlYXR1cmUucHJvcGVydGllc1trZXldID0gdmFsdWU7XG4gICAgfVxufVxuXG5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyA9IFsnVW5rbm93bicsICdQb2ludCcsICdMaW5lU3RyaW5nJywgJ1BvbHlnb24nXTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLmxvYWRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIGxpbmVzID0gW10sXG4gICAgICAgIGxpbmU7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGNtZExlbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgICAgICAgICBjbWQgPSBjbWRMZW4gJiAweDc7XG4gICAgICAgICAgICBsZW5ndGggPSBjbWRMZW4gPj4gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGxlbmd0aC0tO1xuXG4gICAgICAgIGlmIChjbWQgPT09IDEgfHwgY21kID09PSAyKSB7XG4gICAgICAgICAgICB4ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgeSArPSBwYmYucmVhZFNWYXJpbnQoKTtcblxuICAgICAgICAgICAgaWYgKGNtZCA9PT0gMSkgeyAvLyBtb3ZlVG9cbiAgICAgICAgICAgICAgICBpZiAobGluZSkgbGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUucHVzaChuZXcgUG9pbnQoeCwgeSkpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kID09PSA3KSB7XG4gICAgICAgICAgICBsaW5lLnB1c2gobGluZVswXS5jbG9uZSgpKTsgLy8gY2xvc2VQb2x5Z29uXG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBjb21tYW5kICcgKyBjbWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxpbmUpIGxpbmVzLnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gbGluZXM7XG59O1xuXG5WZWN0b3JUaWxlRmVhdHVyZS5wcm90b3R5cGUuYmJveCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYmYgPSB0aGlzLl9wYmY7XG4gICAgcGJmLnBvcyA9IHRoaXMuX2dlb21ldHJ5O1xuXG4gICAgdmFyIGVuZCA9IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zLFxuICAgICAgICBjbWQgPSAxLFxuICAgICAgICBsZW5ndGggPSAwLFxuICAgICAgICB4ID0gMCxcbiAgICAgICAgeSA9IDAsXG4gICAgICAgIHgxID0gSW5maW5pdHksXG4gICAgICAgIHgyID0gLUluZmluaXR5LFxuICAgICAgICB5MSA9IEluZmluaXR5LFxuICAgICAgICB5MiA9IC1JbmZpbml0eTtcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgY21kTGVuID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgICAgICAgICAgIGNtZCA9IGNtZExlbiAmIDB4NztcbiAgICAgICAgICAgIGxlbmd0aCA9IGNtZExlbiA+PiAzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGVuZ3RoLS07XG5cbiAgICAgICAgaWYgKGNtZCA9PT0gMSB8fCBjbWQgPT09IDIpIHtcbiAgICAgICAgICAgIHggKz0gcGJmLnJlYWRTVmFyaW50KCk7XG4gICAgICAgICAgICB5ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICAgICAgaWYgKHggPCB4MSkgeDEgPSB4O1xuICAgICAgICAgICAgaWYgKHggPiB4MikgeDIgPSB4O1xuICAgICAgICAgICAgaWYgKHkgPCB5MSkgeTEgPSB5O1xuICAgICAgICAgICAgaWYgKHkgPiB5MikgeTIgPSB5O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY21kICE9PSA3KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vua25vd24gY29tbWFuZCAnICsgY21kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbeDEsIHkxLCB4MiwgeTJdO1xufTtcblxuVmVjdG9yVGlsZUZlYXR1cmUucHJvdG90eXBlLnRvR2VvSlNPTiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZXh0ZW50ICogTWF0aC5wb3coMiwgeiksXG4gICAgICAgIHgwID0gdGhpcy5leHRlbnQgKiB4LFxuICAgICAgICB5MCA9IHRoaXMuZXh0ZW50ICogeSxcbiAgICAgICAgY29vcmRzID0gdGhpcy5sb2FkR2VvbWV0cnkoKSxcbiAgICAgICAgdHlwZSA9IFZlY3RvclRpbGVGZWF0dXJlLnR5cGVzW3RoaXMudHlwZV07XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluZSA9IGNvb3Jkc1tpXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsaW5lLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGxpbmVbal0sIHkyID0gMTgwIC0gKHAueSArIHkwKSAqIDM2MCAvIHNpemU7XG4gICAgICAgICAgICBsaW5lW2pdID0gW1xuICAgICAgICAgICAgICAgIChwLnggKyB4MCkgKiAzNjAgLyBzaXplIC0gMTgwLFxuICAgICAgICAgICAgICAgIDM2MCAvIE1hdGguUEkgKiBNYXRoLmF0YW4oTWF0aC5leHAoeTIgKiBNYXRoLlBJIC8gMTgwKSkgLSA5MFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnUG9pbnQnICYmIGNvb3Jkcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY29vcmRzID0gY29vcmRzWzBdWzBdO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1BvaW50Jykge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgICAgIHR5cGUgPSAnTXVsdGlQb2ludCc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycgJiYgY29vcmRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBjb29yZHMgPSBjb29yZHNbMF07XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnTGluZVN0cmluZycpIHtcbiAgICAgICAgdHlwZSA9ICdNdWx0aUxpbmVTdHJpbmcnO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgICBnZW9tZXRyeToge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHNcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWZWN0b3JUaWxlRmVhdHVyZSA9IHJlcXVpcmUoJy4vdmVjdG9ydGlsZWZlYXR1cmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBWZWN0b3JUaWxlTGF5ZXI7XG5cbmZ1bmN0aW9uIFZlY3RvclRpbGVMYXllcihwYmYsIGVuZCkge1xuICAgIC8vIFB1YmxpY1xuICAgIHRoaXMudmVyc2lvbiA9IDE7XG4gICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICB0aGlzLmV4dGVudCA9IDQwOTY7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuXG4gICAgLy8gUHJpdmF0ZVxuICAgIHRoaXMuX3BiZiA9IHBiZjtcbiAgICB0aGlzLl9rZXlzID0gW107XG4gICAgdGhpcy5fdmFsdWVzID0gW107XG4gICAgdGhpcy5fZmVhdHVyZXMgPSBbXTtcblxuICAgIHBiZi5yZWFkRmllbGRzKHJlYWRMYXllciwgdGhpcywgZW5kKTtcblxuICAgIHRoaXMubGVuZ3RoID0gdGhpcy5fZmVhdHVyZXMubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiByZWFkTGF5ZXIodGFnLCBsYXllciwgcGJmKSB7XG4gICAgaWYgKHRhZyA9PT0gMTUpIGxheWVyLnZlcnNpb24gPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMSkgbGF5ZXIubmFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gICAgZWxzZSBpZiAodGFnID09PSA1KSBsYXllci5leHRlbnQgPSBwYmYucmVhZFZhcmludCgpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gMikgbGF5ZXIuX2ZlYXR1cmVzLnB1c2gocGJmLnBvcyk7XG4gICAgZWxzZSBpZiAodGFnID09PSAzKSBsYXllci5fa2V5cy5wdXNoKHBiZi5yZWFkU3RyaW5nKCkpO1xuICAgIGVsc2UgaWYgKHRhZyA9PT0gNCkgbGF5ZXIuX3ZhbHVlcy5wdXNoKHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRWYWx1ZU1lc3NhZ2UocGJmKSB7XG4gICAgdmFyIHZhbHVlID0gbnVsbCxcbiAgICAgICAgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgICB2YXIgdGFnID0gcGJmLnJlYWRWYXJpbnQoKSA+PiAzO1xuXG4gICAgICAgIHZhbHVlID0gdGFnID09PSAxID8gcGJmLnJlYWRTdHJpbmcoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDIgPyBwYmYucmVhZEZsb2F0KCkgOlxuICAgICAgICAgICAgdGFnID09PSAzID8gcGJmLnJlYWREb3VibGUoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDQgPyBwYmYucmVhZFZhcmludDY0KCkgOlxuICAgICAgICAgICAgdGFnID09PSA1ID8gcGJmLnJlYWRWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDYgPyBwYmYucmVhZFNWYXJpbnQoKSA6XG4gICAgICAgICAgICB0YWcgPT09IDcgPyBwYmYucmVhZEJvb2xlYW4oKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xufVxuXG4vLyByZXR1cm4gZmVhdHVyZSBgaWAgZnJvbSB0aGlzIGxheWVyIGFzIGEgYFZlY3RvclRpbGVGZWF0dXJlYFxuVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5mZWF0dXJlID0gZnVuY3Rpb24oaSkge1xuICAgIGlmIChpIDwgMCB8fCBpID49IHRoaXMuX2ZlYXR1cmVzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHMnKTtcblxuICAgIHRoaXMuX3BiZi5wb3MgPSB0aGlzLl9mZWF0dXJlc1tpXTtcblxuICAgIHZhciBlbmQgPSB0aGlzLl9wYmYucmVhZFZhcmludCgpICsgdGhpcy5fcGJmLnBvcztcbiAgICByZXR1cm4gbmV3IFZlY3RvclRpbGVGZWF0dXJlKHRoaXMuX3BiZiwgZW5kLCB0aGlzLmV4dGVudCwgdGhpcy5fa2V5cywgdGhpcy5fdmFsdWVzKTtcbn07XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsInZhciBidW5kbGVGbiA9IGFyZ3VtZW50c1szXTtcbnZhciBzb3VyY2VzID0gYXJndW1lbnRzWzRdO1xudmFyIGNhY2hlID0gYXJndW1lbnRzWzVdO1xuXG52YXIgc3RyaW5naWZ5ID0gSlNPTi5zdHJpbmdpZnk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICB2YXIgd2tleTtcbiAgICB2YXIgY2FjaGVLZXlzID0gT2JqZWN0LmtleXMoY2FjaGUpO1xuICAgIFxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2FjaGVLZXlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICBpZiAoY2FjaGVba2V5XS5leHBvcnRzID09PSBmbikge1xuICAgICAgICAgICAgd2tleSA9IGtleTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlmICghd2tleSkge1xuICAgICAgICB3a2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgICAgIHZhciB3Y2FjaGUgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjYWNoZUtleXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gY2FjaGVLZXlzW2ldO1xuICAgICAgICAgICAgd2NhY2hlW2tleV0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgICAgc291cmNlc1t3a2V5XSA9IFtcbiAgICAgICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZScsJ21vZHVsZScsJ2V4cG9ydHMnXSwgJygnICsgZm4gKyAnKShzZWxmKScpLFxuICAgICAgICAgICAgd2NhY2hlXG4gICAgICAgIF07XG4gICAgfVxuICAgIHZhciBza2V5ID0gTWF0aC5mbG9vcihNYXRoLnBvdygxNiwgOCkgKiBNYXRoLnJhbmRvbSgpKS50b1N0cmluZygxNik7XG4gICAgXG4gICAgdmFyIHNjYWNoZSA9IHt9OyBzY2FjaGVbd2tleV0gPSB3a2V5O1xuICAgIHNvdXJjZXNbc2tleV0gPSBbXG4gICAgICAgIEZ1bmN0aW9uKFsncmVxdWlyZSddLCdyZXF1aXJlKCcgKyBzdHJpbmdpZnkod2tleSkgKyAnKShzZWxmKScpLFxuICAgICAgICBzY2FjaGVcbiAgICBdO1xuICAgIFxuICAgIHZhciBzcmMgPSAnKCcgKyBidW5kbGVGbiArICcpKHsnXG4gICAgICAgICsgT2JqZWN0LmtleXMoc291cmNlcykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdpZnkoa2V5KSArICc6WydcbiAgICAgICAgICAgICAgICArIHNvdXJjZXNba2V5XVswXVxuICAgICAgICAgICAgICAgICsgJywnICsgc3RyaW5naWZ5KHNvdXJjZXNba2V5XVsxXSkgKyAnXSdcbiAgICAgICAgICAgIDtcbiAgICAgICAgfSkuam9pbignLCcpXG4gICAgICAgICsgJ30se30sWycgKyBzdHJpbmdpZnkoc2tleSkgKyAnXSknXG4gICAgO1xuICAgIFxuICAgIHZhciBVUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkwgfHwgd2luZG93Lm1velVSTCB8fCB3aW5kb3cubXNVUkw7XG4gICAgXG4gICAgcmV0dXJuIG5ldyBXb3JrZXIoVVJMLmNyZWF0ZU9iamVjdFVSTChcbiAgICAgICAgbmV3IEJsb2IoW3NyY10sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSlcbiAgICApKTtcbn07XG4iXX0=
>>>>>>> Stashed changes